Skip to content

Commit

Permalink
Optimize terrain meshing
Browse files Browse the repository at this point in the history
  • Loading branch information
jeickhoff committed Jul 13, 2023
1 parent 79ff45a commit f556ef8
Show file tree
Hide file tree
Showing 17 changed files with 444 additions and 475 deletions.
2 changes: 1 addition & 1 deletion Assets/Materials/Shaders/VoxelShader.shader
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Shader "Custom/VoxelShader"
SubShader
{

// Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True"}
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True"}
Pass
{
Name "Forward"
Expand Down
2 changes: 1 addition & 1 deletion Assets/Materials/TerrainMaterial.mat
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Material:
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
m_CustomRenderQueue: 3000
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
Expand Down
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Assets/Scenes/AuthoringScene/AuthoringScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,13 @@ MonoBehaviour:
- 1
- 1
- 1
seed: 43
seed: 44
initialAreas:
x: 4
y: 2
z: 4
playerViewRange: 2
terrainSpawnRange: 2
maxChunkSpawnsPerTick: 50
blocksPerAreaSide: 16
YBounds:
Expand Down
81 changes: 73 additions & 8 deletions Assets/Scripts/Player/PlayerActionSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;

namespace Opencraft.Player
Expand All @@ -15,7 +16,9 @@ namespace Opencraft.Player
[BurstCompile]
public partial struct PlayerActionSystem : ISystem
{
private BufferLookup<TerrainBlocks> _terrainBlockLookup;
private BufferLookup<TerrainBlocks> _terrainBlocksBufferLookup;
private BufferLookup<TerrainColMinY> _terrainColumnMinBufferLookup;
private BufferLookup<TerrainColMaxY> _terrainColumnMaxBufferLookup;
private NativeArray<Entity> terrainAreasEntities;

[BurstCompile]
Expand All @@ -25,15 +28,19 @@ public void OnCreate(ref SystemState state)
state.RequireForUpdate<Authoring.Player>();
state.RequireForUpdate<TerrainArea>();
state.RequireForUpdate<TerrainSpawner>();
_terrainBlockLookup = state.GetBufferLookup<TerrainBlocks>(false);

_terrainBlocksBufferLookup = state.GetBufferLookup<TerrainBlocks>(false);
_terrainColumnMinBufferLookup= state.GetBufferLookup<TerrainColMinY>(false);
_terrainColumnMaxBufferLookup= state.GetBufferLookup<TerrainColMaxY>(false);

}

[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.CompleteDependency();
_terrainBlockLookup.Update(ref state);
_terrainBlocksBufferLookup.Update(ref state);
_terrainColumnMinBufferLookup.Update(ref state);
_terrainColumnMaxBufferLookup.Update(ref state);
var terrainAreasQuery = SystemAPI.QueryBuilder().WithAll<TerrainArea, LocalTransform>().Build();
terrainAreasEntities = terrainAreasQuery.ToEntityArray(state.WorldUpdateAllocator);

Expand All @@ -44,12 +51,58 @@ public void OnUpdate(ref SystemState state)
{

Entity terrainAreaEntity = terrainAreasEntities[player.SelectedBlock.terrainAreaIndex];
if(_terrainBlockLookup.TryGetBuffer(terrainAreaEntity, out DynamicBuffer<TerrainBlocks> terrainBlocks))
if(_terrainBlocksBufferLookup.TryGetBuffer(terrainAreaEntity, out DynamicBuffer<TerrainBlocks> terrainBlocks))
{
int blockIndex = TerrainUtilities.BlockLocationToIndex(ref player.SelectedBlock.blockLoc);
int3 blockLoc = player.SelectedBlock.blockLoc;
int blockIndex = TerrainUtilities.BlockLocationToIndex(ref blockLoc);
int colIndex = TerrainUtilities.BlockLocationToColIndex(ref blockLoc);
DynamicBuffer<BlockType> blocks = terrainBlocks.Reinterpret<BlockType>();
if (blocks[blockIndex] != BlockType.Air)
{
var colMins = _terrainColumnMinBufferLookup[terrainAreaEntity].Reinterpret<byte>();
var colMaxes = _terrainColumnMaxBufferLookup[terrainAreaEntity].Reinterpret<byte>();
int minY = colMins[colIndex];
int maxY = colMaxes[colIndex];
int bps = Constants.BlocksPerSide.Data;
// If removed block is top or bottom of a column, search for new top or bottom and update heightmaps
if (blockLoc.y == minY)
{
// Search upwards for new min y
for (int y = 1; y < bps - blockLoc.y; y++)
{
if (blocks[blockIndex + y] != BlockType.Air)
{
// found a non-empty block
colMins[colIndex] = (byte)(blockLoc.y + y);
break;
}

if (y == (bps - blockLoc.y) - 1)
{
// no non-empty blocks found, set min to a max value
colMins[colIndex] = (byte)bps;
}
}
}
if (blockLoc.y + 1 == maxY)
{
// Search downwards for new max
for (int y = 1; y < blockLoc.y ; y++)
{
if (blocks[blockIndex - y] != BlockType.Air)
{
// found a non-empty block
colMaxes[colIndex] = (byte)(blockLoc.y-y+1);
break;
}

if (y == blockLoc.y-1)
{
// no non-empty blocks found, set max to a min value
colMaxes[colIndex] = 0;
}
}
}
blocks[blockIndex] = BlockType.Air;
}
}
Expand All @@ -59,12 +112,24 @@ public void OnUpdate(ref SystemState state)
if (player.Input.SecondaryAction.IsSet && player.SelectedBlock.neighborTerrainAreaIndex != -1)
{
Entity terrainAreaEntity = terrainAreasEntities[player.SelectedBlock.neighborTerrainAreaIndex];
if(_terrainBlockLookup.TryGetBuffer(terrainAreaEntity, out DynamicBuffer<TerrainBlocks> terrainBlocks))
if(_terrainBlocksBufferLookup.TryGetBuffer(terrainAreaEntity, out DynamicBuffer<TerrainBlocks> terrainBlocks))
{
int blockIndex = TerrainUtilities.BlockLocationToIndex(ref player.SelectedBlock.neighborBlockLoc);
int3 blockLoc = player.SelectedBlock.neighborBlockLoc;
int blockIndex = TerrainUtilities.BlockLocationToIndex(ref blockLoc);
int colIndex = TerrainUtilities.BlockLocationToColIndex(ref blockLoc);
DynamicBuffer<BlockType> blocks = terrainBlocks.Reinterpret<BlockType>();
if (blocks[blockIndex] == BlockType.Air)
{
var colMins = _terrainColumnMinBufferLookup[terrainAreaEntity].Reinterpret<byte>();
var colMaxes = _terrainColumnMaxBufferLookup[terrainAreaEntity].Reinterpret<byte>();
int minY = colMins[colIndex];
int maxY = colMaxes[colIndex];
// If new block is the top or bottom of a column, update the column heightmaps
if (blockLoc.y < minY)
colMins[colIndex] = (byte) blockLoc.y;
if (blockLoc.y + 1 > maxY)
colMaxes[colIndex] = (byte) (blockLoc.y + 1);
// todo ability to place something other than stone
blocks[blockIndex] = BlockType.Stone;
}
}
Expand Down
2 changes: 1 addition & 1 deletion Assets/Scripts/Player/PlayerSelectedBlockSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void OnUpdate(ref SystemState state)
out DynamicBuffer<TerrainBlocks> terrainBlocks))
{
int blockIndex = TerrainUtilities.BlockLocationToIndex(ref blockLoc);
if (terrainBlocks[blockIndex].Value != BlockType.Air)
if (terrainBlocks[blockIndex].type != BlockType.Air)
{
// found selected block
player.SelectedBlock.blockLoc = blockLoc;
Expand Down
Loading

0 comments on commit f556ef8

Please sign in to comment.