structures, also they're a little broken, they need to check for neighbouring YZones as well
This commit is contained in:
parent
a0b00b0f1c
commit
d1abde919d
12 changed files with 604 additions and 134 deletions
|
|
@ -200,6 +200,7 @@ public class VulkanRenderer implements Renderer {
|
|||
int Index = materialsCache.GetPosition("VoxelTerrain");
|
||||
int Index2 = materialsCache.GetPosition("Blueleaf");
|
||||
int Index3 = materialsCache.GetPosition("Blueleaf2");
|
||||
|
||||
Voxel grassVoxel = new Voxel(Index, 0,
|
||||
new Vector2i[]{positionArr[0][1], positionArr[0][3]},
|
||||
new Vector2i[]{positionArr[1][0], positionArr[1][0]},
|
||||
|
|
@ -373,8 +374,14 @@ public class VulkanRenderer implements Renderer {
|
|||
Biome GreenBiome = new Biome(1,2,3,4,new int[]{5,6,7,4},new int[]{4,4,4,4},new int[]{4,18,16,17});
|
||||
Biome Blueleaf = new Biome(8,9,3,10,new int[]{11,19,20,14},new int[]{5,6,7,8},new int[]{15,16,17,18});
|
||||
|
||||
VoxelWorldManager.AddBiome(Blueleaf, "blueleaf");
|
||||
VoxelWorldManager.AddBiome(GreenBiome, "greenBiome");
|
||||
VoxelWorldManager.AddBiome(Blueleaf, "blueleaf");
|
||||
|
||||
VoxelWorldManager.GenerateExampleTree(5,8,5,0,1,6,7,"green_tree", 15, 0.5f);
|
||||
VoxelWorldManager.GenerateExampleTree(12,16,12,0,1,6,7,"green_tree_tall", 15, 0.5f);
|
||||
VoxelWorldManager.GenerateExampleTree(7,12,7,1,8,6,20,"blue_tree", 30,0.25f);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public GuiRenderer GetGUIRenderer(){return GuiRender;}
|
||||
|
|
|
|||
|
|
@ -25,19 +25,24 @@ public class SharedVoxelTerrainResources {
|
|||
public static final int DRAW_INDIRECT_COMMAND_SIZE = 4 * Integer.BYTES;
|
||||
public static final int COUNTER_BUFFER_SIZE = Integer.BYTES;
|
||||
|
||||
public static final int TERRAIN_GENERATION_PUSH_CONSTANT_SIZE = Integer.BYTES * 8;
|
||||
public static final int TERRAIN_GENERATION_PUSH_CONSTANT_SIZE = Integer.BYTES * 10;
|
||||
|
||||
public static final int MAX_VOXEL_TYPES = 256;
|
||||
public static final int MAX_BIOME_TYPES = 256;
|
||||
public static final int VOXEL_REG_DATA_SIZE = 104;
|
||||
public static final int BIOME_REG_DATA_SIZE = 64;
|
||||
|
||||
public static final int MAX_STRUCTURE_TYPES = 128;
|
||||
public static final int STRUCTURE_REG_DATA_SIZE = 36;
|
||||
public static final int MAX_STRUCTURE_BLOCKS = 16 * 24 * 16;
|
||||
|
||||
private static final String DESC_ID_VOXEL_GENERATION = "VOXEL_SHARED_DESC_GENERATION";
|
||||
private static final String DESC_ID_RESET = "VOXEL_SHARED_DESC_RESET";
|
||||
private static final String DESC_ID_MESH = "VOXEL_SHARED_DESC_MESH";
|
||||
private static final String DESC_ID_FACE_GRAPHICS = "VOXEL_SHARED_DESC_FACE_GRAPHICS";
|
||||
private static final String DESC_ID_VOXEL_REG = "VOXEL_REGISTRY";
|
||||
private static final String DESC_ID_BIOME_REG = "BIOME_REGISTRY";
|
||||
private static final String DESC_ID_STRUCTURE_REG = "STRUCTURE_REGISTRY";
|
||||
|
||||
private final VoxelMeshPool meshPool;
|
||||
|
||||
|
|
@ -45,6 +50,8 @@ public class SharedVoxelTerrainResources {
|
|||
private final VulkanBuffer counters;
|
||||
private final VulkanBuffer voxelRegistryBuffer;
|
||||
private final VulkanBuffer biomeRegistryBuffer;
|
||||
private final VulkanBuffer structureRegistryBuffer;
|
||||
private final VulkanBuffer structureVoxelDataBuffer;
|
||||
|
||||
private final DescriptorSetLayout voxelGenerationLayout;
|
||||
private final DescriptorSetLayout resetLayout;
|
||||
|
|
@ -52,6 +59,7 @@ public class SharedVoxelTerrainResources {
|
|||
private final DescriptorSetLayout faceGraphicsLayout;
|
||||
private final DescriptorSetLayout voxelDeclarationLayout;
|
||||
private final DescriptorSetLayout biomeDeclarationLayout;
|
||||
private final DescriptorSetLayout structureDeclarationLayout;
|
||||
|
||||
private static final String MESH_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/meshGenerationShared.glsl";
|
||||
private static final String VOXEL_GENERATION_GLSL = "resources/EngineResources/VoxelComputeShaders/voxelGenerationShared.glsl";
|
||||
|
|
@ -82,6 +90,14 @@ public class SharedVoxelTerrainResources {
|
|||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
structureRegistryBuffer = new VulkanBuffer(VkCtx, (long) MAX_STRUCTURE_TYPES * STRUCTURE_REG_DATA_SIZE,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
structureVoxelDataBuffer = new VulkanBuffer(VkCtx, (long) MAX_STRUCTURE_TYPES * MAX_STRUCTURE_BLOCKS * Integer.BYTES,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
|
||||
voxelGenerationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{
|
||||
new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
|
|
@ -109,6 +125,10 @@ public class SharedVoxelTerrainResources {
|
|||
biomeDeclarationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{
|
||||
new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
});
|
||||
structureDeclarationLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation[]{
|
||||
new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_COMPUTE_BIT),
|
||||
new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
});
|
||||
|
||||
createDescriptorSets(VkCtx);
|
||||
|
||||
|
|
@ -123,7 +143,7 @@ public class SharedVoxelTerrainResources {
|
|||
resetPipeline = new ComputePipeline(VkCtx,resetShader,new DescriptorSetLayout[]{resetLayout},generationPushConstants);
|
||||
|
||||
voxelGenerationPipeline = new ComputePipeline(VkCtx,voxelShader,
|
||||
new DescriptorSetLayout[]{voxelGenerationLayout,biomeDeclarationLayout},generationPushConstants);
|
||||
new DescriptorSetLayout[]{voxelGenerationLayout,biomeDeclarationLayout, structureDeclarationLayout},generationPushConstants);
|
||||
|
||||
meshGenerationPipeline = new ComputePipeline(VkCtx, meshShader,
|
||||
new DescriptorSetLayout[]{meshGenerationLayout, voxelDeclarationLayout}, generationPushConstants);
|
||||
|
|
@ -166,6 +186,58 @@ public class SharedVoxelTerrainResources {
|
|||
DescriptorSet biomeDeclareDescriptorSet = allocator.AddDescriptorSet(device, DESC_ID_BIOME_REG, biomeDeclarationLayout);
|
||||
biomeDeclareDescriptorSet.SetBuffer(device, biomeRegistryBuffer, biomeRegistryBuffer.GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
|
||||
DescriptorSet structureDeclareDescriptorSet = allocator.AddDescriptorSet(device, DESC_ID_STRUCTURE_REG, structureDeclarationLayout);
|
||||
structureDeclareDescriptorSet.SetBuffer(device, structureRegistryBuffer, structureRegistryBuffer.GetRequestedSize(), 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
structureDeclareDescriptorSet.SetBuffer(device, structureVoxelDataBuffer, structureVoxelDataBuffer.GetRequestedSize(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void UploadStructureRegistryAndData(VulkanContext VkCtx, List<VoxelStructure> structureReg, List<Integer> structureData) {
|
||||
int structureCount = Math.min(structureReg.size(), MAX_STRUCTURE_TYPES);
|
||||
|
||||
long structureRegistryMemoryAddr = structureRegistryBuffer.MapMemory(VkCtx);
|
||||
ByteBuffer structureRegistryByteBuffer = MemoryUtil.memByteBuffer(
|
||||
structureRegistryMemoryAddr,
|
||||
(int) structureRegistryBuffer.GetRequestedSize()
|
||||
);
|
||||
|
||||
for (int i = 0; i < structureCount; i++) {
|
||||
VoxelStructure structure = structureReg.get(i);
|
||||
int base = i * STRUCTURE_REG_DATA_SIZE;
|
||||
|
||||
int spawnChance = Math.round(structure.SpawnChance() * 1000.0f);
|
||||
spawnChance = Math.clamp(spawnChance, 0, 1000);
|
||||
|
||||
structureRegistryByteBuffer.putInt(base + 0, structure.SizeX());
|
||||
structureRegistryByteBuffer.putInt(base + 4, structure.SizeY());
|
||||
structureRegistryByteBuffer.putInt(base + 8, structure.SizeZ());
|
||||
structureRegistryByteBuffer.putInt(base + 12, structure.BlockOffset());
|
||||
structureRegistryByteBuffer.putInt(base + 16, structure.SpawnSpacing());
|
||||
structureRegistryByteBuffer.putInt(base + 20, spawnChance);
|
||||
structureRegistryByteBuffer.putInt(base + 24, structure.AllowedBiome());
|
||||
structureRegistryByteBuffer.putInt(base + 28, structure.Flags());
|
||||
structureRegistryByteBuffer.putInt(base + 32, structure.GroundBlock());
|
||||
}
|
||||
|
||||
structureRegistryBuffer.UnMapMemory(VkCtx);
|
||||
|
||||
int blockCount = Math.min(
|
||||
structureData.size(),
|
||||
(int) (structureVoxelDataBuffer.GetRequestedSize() / Integer.BYTES)
|
||||
);
|
||||
|
||||
long structureVoxelDataMemoryAddr = structureVoxelDataBuffer.MapMemory(VkCtx);
|
||||
ByteBuffer structureVoxelDataByteBuffer = MemoryUtil.memByteBuffer(
|
||||
structureVoxelDataMemoryAddr,
|
||||
(int) structureVoxelDataBuffer.GetRequestedSize()
|
||||
);
|
||||
|
||||
for (int i = 0; i < blockCount; i++) {
|
||||
structureVoxelDataByteBuffer.putInt(i * Integer.BYTES, structureData.get(i));
|
||||
}
|
||||
|
||||
structureVoxelDataBuffer.UnMapMemory(VkCtx);
|
||||
}
|
||||
|
||||
public void UploadBiomeRegistry(VulkanContext VkCtx, List<Biome> biomeReg) {
|
||||
|
|
@ -269,10 +341,13 @@ public class SharedVoxelTerrainResources {
|
|||
return DESC_ID_BIOME_REG;
|
||||
}
|
||||
|
||||
public String structureRegDescriptorID() {
|
||||
return DESC_ID_STRUCTURE_REG;
|
||||
}
|
||||
|
||||
public String resetDescriptorId() {
|
||||
return DESC_ID_RESET;
|
||||
}
|
||||
|
||||
public String meshDescriptorId() {
|
||||
return DESC_ID_MESH;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration;
|
||||
|
||||
public final class StructureFlags {
|
||||
public static final int REPLACE_AIR_ONLY = 1;
|
||||
public static final int REPLACE_FOLIAGE = 2;
|
||||
public static final int REQUIRE_FLAT_GROUND = 4;
|
||||
public static final int HAS_FOUNDATION = 8;
|
||||
}
|
||||
|
|
@ -41,12 +41,16 @@ public class VoxelChunkGenerator {
|
|||
pushConstants.putInt(20, VoxelWorldManager.GetVoxelTypeCount());
|
||||
pushConstants.putInt(24, indirectCommandIndex);
|
||||
pushConstants.putInt(28, VoxelWorldManager.GetBiomeTypeCount());
|
||||
pushConstants.putInt(32, VoxelWorldManager.GetStructureTypeCount());
|
||||
pushConstants.putInt(36, VoxelWorldManager.GetWorldSeed());
|
||||
|
||||
LongBuffer resetDescriptorSet = stack.longs(allocator.GetDescriptorSet(
|
||||
resources.resetDescriptorId()).GetVkDescriptorSet());
|
||||
LongBuffer voxelDescriptorSet = stack.longs(allocator.GetDescriptorSet(
|
||||
resources.voxelGenerationDescriptorId()).GetVkDescriptorSet(),
|
||||
allocator.GetDescriptorSet(resources.biomeRegDescriptorID()).GetVkDescriptorSet());
|
||||
LongBuffer voxelDescriptorSet = stack.longs(
|
||||
allocator.GetDescriptorSet(resources.voxelGenerationDescriptorId()).GetVkDescriptorSet(),
|
||||
allocator.GetDescriptorSet(resources.biomeRegDescriptorID()).GetVkDescriptorSet(),
|
||||
allocator.GetDescriptorSet(resources.structureRegDescriptorID()).GetVkDescriptorSet()
|
||||
);
|
||||
LongBuffer meshDescriptorSet = stack.longs(
|
||||
allocator.GetDescriptorSet(resources.meshDescriptorId()).GetVkDescriptorSet(),
|
||||
allocator.GetDescriptorSet(resources.voxelRegDescriptorID()).GetVkDescriptorSet());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Computing.VoxelTerrainGeneration;
|
||||
|
||||
public record VoxelStructure(int SizeX, int SizeY, int SizeZ, int BlockOffset, int SpawnSpacing, float SpawnChance, int AllowedBiome, int GroundBlock, int Flags) {
|
||||
}
|
||||
|
|
@ -9,11 +9,13 @@ import org.joml.*;
|
|||
import org.lwjgl.vulkan.VkCommandBuffer;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.lang.Math;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static org.lwjgl.vulkan.VK13.*;
|
||||
|
||||
|
|
@ -27,14 +29,97 @@ public class VoxelWorldManager {
|
|||
private static final ConcurrentHashMap<Vector3i, Boolean> KnownChunks = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Vector3i, VoxelChunkVisibility> CulledChunks = new ConcurrentHashMap<>();
|
||||
|
||||
private static final List<Voxel> VoxelRegistry = new java.util.concurrent.CopyOnWriteArrayList<>();
|
||||
private static final List<Voxel> VoxelRegistry = new CopyOnWriteArrayList<>();
|
||||
private static final ConcurrentHashMap<String, Integer> VoxelNameToIndex = new ConcurrentHashMap<>();
|
||||
private static volatile boolean RegistryDirty = false;
|
||||
|
||||
private static final List<Biome> BiomeRegistry = new java.util.concurrent.CopyOnWriteArrayList<>();
|
||||
private static final List<Biome> BiomeRegistry = new CopyOnWriteArrayList<>();
|
||||
private static final ConcurrentHashMap<String, Integer> BiomeNameToIndex = new ConcurrentHashMap<>();
|
||||
private static volatile boolean BiomeRegistryDirty = false;
|
||||
|
||||
private static final List<VoxelStructure> StructureRegistry = new CopyOnWriteArrayList<>();
|
||||
private static final List<Integer> StructureBlockData = new CopyOnWriteArrayList<>();
|
||||
private static final ConcurrentHashMap<String, Integer> StructureNameToIndex =new ConcurrentHashMap<>();
|
||||
private static volatile boolean StructureRegistryDirty = false;
|
||||
|
||||
private static int worldSeed = 12432450;
|
||||
|
||||
public static int GetWorldSeed(){
|
||||
return worldSeed;
|
||||
}
|
||||
public static int structureIndex(int x, int y, int z, int sizeY, int sizeZ) {
|
||||
return x * sizeY * sizeZ + y * sizeZ + z;
|
||||
}
|
||||
|
||||
public static synchronized void AddStructure(String name, int sizeX, int sizeY, int sizeZ, int spawnSpacing,
|
||||
float spawnChance, int allowedBiome, int groundBlock, int flags,
|
||||
int[] denseBlocks) {
|
||||
int blockOffset = StructureBlockData.size();
|
||||
|
||||
for (int block : denseBlocks) {
|
||||
StructureBlockData.add(block);
|
||||
}
|
||||
|
||||
VoxelStructure structure = new VoxelStructure(sizeX, sizeY, sizeZ, blockOffset,
|
||||
spawnSpacing, spawnChance, allowedBiome, groundBlock, flags);
|
||||
|
||||
Integer existing = StructureNameToIndex.get(name);
|
||||
|
||||
if (existing != null) {
|
||||
StructureRegistry.set(existing, structure);
|
||||
} else {
|
||||
StructureNameToIndex.put(name, StructureRegistry.size());
|
||||
StructureRegistry.add(structure);
|
||||
}
|
||||
|
||||
StructureRegistryDirty = true;
|
||||
}
|
||||
public static List<VoxelStructure> GetStructureRegistry() {
|
||||
return new ArrayList<>(StructureRegistry);
|
||||
}
|
||||
|
||||
public static List<Integer> GetStructureBlockData() {
|
||||
return new ArrayList<>(StructureBlockData);
|
||||
}
|
||||
|
||||
public static VoxelStructure GetStructure(String name) {
|
||||
Integer idx = StructureNameToIndex.get(name);
|
||||
return idx == null ? null : StructureRegistry.get(idx);
|
||||
}
|
||||
|
||||
public static int GetStructureTypeID(String name) {
|
||||
Integer idx = StructureNameToIndex.get(name);
|
||||
return idx == null ? -1 : idx + 1;
|
||||
}
|
||||
|
||||
public static int GetStructureTypeCount() {
|
||||
return StructureRegistry.size();
|
||||
}
|
||||
|
||||
public static synchronized void GenerateExampleTree(int sizeX, int sizeY, int sizeZ, int Biome, int GroundVoxel, int log, int leaves, String name, int Spacing, float Chance){
|
||||
int[] blocks = new int[sizeX * sizeY * sizeZ];
|
||||
|
||||
for (int y = 0; y < sizeY/2; y++) {
|
||||
blocks[structureIndex(sizeX/2, y, sizeZ/2, sizeY, sizeZ)] = log;
|
||||
}
|
||||
|
||||
for (int x = 0; x < sizeX; x++) {
|
||||
for (int y = sizeY/2; y < sizeY; y++) {
|
||||
for (int z = 0; z < sizeZ; z++) {
|
||||
int dx = x - sizeX/2;
|
||||
int dy = y - sizeY/5 * 3;
|
||||
int dz = z - sizeZ/2;
|
||||
|
||||
if (dx * dx + dy * dy + dz * dz <= sizeX) {
|
||||
blocks[structureIndex(x, y, z, sizeY, sizeZ)] = leaves;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VoxelWorldManager.AddStructure(name, sizeX, sizeY, sizeZ, Spacing, Chance,
|
||||
Biome, GroundVoxel, 0, blocks);
|
||||
}
|
||||
|
||||
public static synchronized void AddVoxel(Voxel voxel, String name) {
|
||||
Integer existing = VoxelNameToIndex.get(name);
|
||||
if (existing != null) {
|
||||
|
|
@ -198,6 +283,10 @@ public class VoxelWorldManager {
|
|||
BiomeRegistryDirty = false;
|
||||
Resources.UploadBiomeRegistry(VkCtx, GetBiomeRegistry());
|
||||
}
|
||||
if (StructureRegistryDirty) {
|
||||
StructureRegistryDirty = false;
|
||||
Resources.UploadStructureRegistryAndData(VkCtx, GetStructureRegistry(), GetStructureBlockData());
|
||||
}
|
||||
|
||||
if (VoxelRegistry.isEmpty()) {
|
||||
return; // nothing to mesh against yet
|
||||
|
|
@ -292,19 +381,19 @@ public class VoxelWorldManager {
|
|||
KnownChunks.remove(pos);
|
||||
return true;
|
||||
}
|
||||
// int dx = pos.x - centerChunk.x;
|
||||
// int dy = pos.y - centerChunk.y;
|
||||
// int dz = pos.z - centerChunk.z;
|
||||
//
|
||||
// int distSq = dx * dx + dy * dy + dz * dz;
|
||||
// if (distSq > maxDistSq) {
|
||||
// RenderChunk chunk = entry.getValue();
|
||||
//
|
||||
// Resources.meshPool().free(chunk);
|
||||
// KnownChunks.remove(pos);
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
int dx = pos.x - centerChunk.x;
|
||||
int dy = pos.y - centerChunk.y;
|
||||
int dz = pos.z - centerChunk.z;
|
||||
|
||||
int distSq = dx * dx + dy * dy + dz * dz;
|
||||
if (distSq > maxDistSq) {
|
||||
RenderChunk chunk = entry.getValue();
|
||||
|
||||
Resources.meshPool().free(chunk);
|
||||
KnownChunks.remove(pos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue