riversong code showcase
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[BurstCompile]
|
||||
public struct GenerateTerrainChunkJob : IJobParallelFor
|
||||
{
|
||||
public int2 WorldSize;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<int2> ChunkCoordsArray;
|
||||
|
||||
public int ChunkSize;
|
||||
|
||||
[ReadOnly]
|
||||
public NativeArray<int> Heightmap;
|
||||
|
||||
[NativeDisableParallelForRestriction]
|
||||
public Mesh.MeshDataArray MeshDataArray;
|
||||
|
||||
public void Execute(int index)
|
||||
{
|
||||
var coords = ChunkCoordsArray[index];
|
||||
|
||||
var vertexAttributes = new NativeArray<VertexAttributeDescriptor>(3, Allocator.Temp);
|
||||
vertexAttributes[0] = new VertexAttributeDescriptor(VertexAttribute.Position);
|
||||
vertexAttributes[1] = new VertexAttributeDescriptor(VertexAttribute.Normal);
|
||||
vertexAttributes[2] = new VertexAttributeDescriptor(VertexAttribute.TexCoord0, dimension: 2);
|
||||
|
||||
var tileCount = ChunkSize * ChunkSize;
|
||||
var vertexTemp = new NativeList<Vertex>(20 * tileCount, Allocator.Temp);
|
||||
var indexTemp = new NativeList<int>(30 * tileCount, Allocator.Temp);
|
||||
|
||||
var tileMin = coords * ChunkSize;
|
||||
var tileMax = math.min(tileMin + ChunkSize, WorldSize);
|
||||
var tile = int2.zero;
|
||||
|
||||
for (tile.y = tileMin.y; tile.y < tileMax.y; tile.y++)
|
||||
for (tile.x = tileMin.x; tile.x < tileMax.x; tile.x++)
|
||||
{
|
||||
var h = Heightmap[math.mad(tile.y, WorldSize.x, tile.x)];
|
||||
if (h == 0) continue;
|
||||
|
||||
var v0 = new Vertex(new float3(tile.x, h, tile.y), math.up(), float2.zero);
|
||||
var v1 = new Vertex(new float3(tile.x, h, tile.y + 1), math.up(), float2.zero);
|
||||
var v2 = new Vertex(new float3(tile.x + 1, h, tile.y + 1), math.up(), float2.zero);
|
||||
var v3 = new Vertex(new float3(tile.x + 1, h, tile.y), math.up(), float2.zero);
|
||||
WriteQuad(vertexTemp, indexTemp, v0, v1, v2, v3, false);
|
||||
}
|
||||
|
||||
var cliffSubMeshIndexStart = indexTemp.Length;
|
||||
|
||||
for (tile.y = tileMin.y; tile.y < tileMax.y && tile.y < WorldSize.y - 1; tile.y++)
|
||||
for (tile.x = tileMin.x; tile.x < tileMax.x && tile.x < WorldSize.x - 1; tile.x++)
|
||||
{
|
||||
var h = Heightmap[math.mad(tile.y, WorldSize.x, tile.x)];
|
||||
|
||||
var hx = Heightmap[math.mad(tile.y, WorldSize.x, tile.x + 1)];
|
||||
if (h != hx)
|
||||
{
|
||||
var hMin = math.min(h, hx);
|
||||
var hMax = math.max(h, hx);
|
||||
|
||||
for (var y = hMin; y < hMax; y++)
|
||||
{
|
||||
var bottomUV = math.unlerp(hMin, hMax, y);
|
||||
var topUV = math.unlerp(hMin, hMax, y + 1);
|
||||
|
||||
var normal = h > hx ? math.right() : math.left();
|
||||
var v0 = new Vertex(new float3(tile.x + 1, y, tile.y), normal, bottomUV);
|
||||
var v1 = new Vertex(new float3(tile.x + 1, y + 1, tile.y), normal, topUV);
|
||||
var v2 = new Vertex(new float3(tile.x + 1, y + 1, tile.y + 1), normal, topUV);
|
||||
var v3 = new Vertex(new float3(tile.x + 1, y, tile.y + 1), normal, bottomUV);
|
||||
WriteQuad(vertexTemp, indexTemp, v0, v1, v2, v3, h < hx);
|
||||
}
|
||||
}
|
||||
|
||||
var hz = Heightmap[math.mad(tile.y + 1, WorldSize.x, tile.x)];
|
||||
if (h != hz)
|
||||
{
|
||||
var hMin = math.min(h, hz);
|
||||
var hMax = math.max(h, hz);
|
||||
|
||||
for (var y = hMin; y < hMax; y++)
|
||||
{
|
||||
var bottomUV = math.unlerp(hMin, hMax, y);
|
||||
var topUV = math.unlerp(hMin, hMax, y + 1);
|
||||
|
||||
var normal = h > hz ? math.forward() : math.back();
|
||||
var v0 = new Vertex(new float3(tile.x + 1, y, tile.y + 1), normal, bottomUV);
|
||||
var v1 = new Vertex(new float3(tile.x + 1, y + 1, tile.y + 1), normal, topUV);
|
||||
var v2 = new Vertex(new float3(tile.x, y + 1, tile.y + 1), normal, topUV);
|
||||
var v3 = new Vertex(new float3(tile.x, y, tile.y + 1), normal, bottomUV);
|
||||
WriteQuad(vertexTemp, indexTemp, v0, v1, v2, v3, h < hz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mesh = MeshDataArray[index];
|
||||
|
||||
mesh.SetVertexBufferParams(vertexTemp.Length, vertexAttributes);
|
||||
|
||||
var chunkVertexData = mesh.GetVertexData<Vertex>();
|
||||
chunkVertexData.CopyFrom(vertexTemp.AsArray());
|
||||
|
||||
mesh.SetIndexBufferParams(indexTemp.Length, IndexFormat.UInt32);
|
||||
var chunkIndexData = mesh.GetIndexData<int>();
|
||||
chunkIndexData.CopyFrom(indexTemp.AsArray());
|
||||
|
||||
mesh.subMeshCount = indexTemp.Length > cliffSubMeshIndexStart ? 2 : 1;
|
||||
mesh.SetSubMesh(0, new SubMeshDescriptor(0, cliffSubMeshIndexStart));
|
||||
if (mesh.subMeshCount > 1) mesh.SetSubMesh(1, new SubMeshDescriptor(cliffSubMeshIndexStart, chunkIndexData.Length - cliffSubMeshIndexStart));
|
||||
}
|
||||
|
||||
private void WriteQuad(NativeList<Vertex> vertices, NativeList<int> indices, in Vertex v0, in Vertex v1, in Vertex v2, in Vertex v3, bool flip)
|
||||
{
|
||||
var v = vertices.Length;
|
||||
|
||||
vertices.AddNoResize(v0);
|
||||
vertices.AddNoResize(v1);
|
||||
vertices.AddNoResize(v2);
|
||||
vertices.AddNoResize(v3);
|
||||
|
||||
var i0 = v + (flip ? 2 : 0);
|
||||
var i1 = v + 1;
|
||||
var i2 = v + (flip ? 0 : 2);
|
||||
var i3 = v + 3;
|
||||
|
||||
indices.AddNoResize(i0);
|
||||
indices.AddNoResize(i1);
|
||||
indices.AddNoResize(i2);
|
||||
indices.AddNoResize(i2);
|
||||
indices.AddNoResize(i3);
|
||||
indices.AddNoResize(i0);
|
||||
}
|
||||
|
||||
private struct Vertex
|
||||
{
|
||||
public float3 Position;
|
||||
|
||||
public float3 Normal;
|
||||
|
||||
public float2 TexCoord0;
|
||||
|
||||
public Vertex(float3 position, float3 normal, float2 texCoord0)
|
||||
{
|
||||
Position = position;
|
||||
Normal = normal;
|
||||
TexCoord0 = texCoord0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user