rocky plains biome
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-04-02 13:37:25 -04:00
parent c3f372d600
commit 21c73c6672
18 changed files with 232 additions and 17 deletions

View File

@ -24,7 +24,15 @@
], ],
"surfaceGenerationParams": { "surfaceGenerationParams": {
"surfaceGenTag": "plains", "surfaceGenTag": "plains",
"heightOffset": 10 "heightOffset": 10,
"floorVariants": [
{
"voxelId": 2,
"frequency": 1.0,
"dispersion": 1.0,
"priority": 1.0
}
]
} }
}, },
{ {
@ -53,6 +61,12 @@
"surfaceGenTag": "hills", "surfaceGenTag": "hills",
"heightOffset": 10, "heightOffset": 10,
"floorVariants": [ "floorVariants": [
{
"voxelId": 2,
"frequency": 1.0,
"dispersion": 1.0,
"priority": 1.0
}
], ],
"foliageDescriptions": [ "foliageDescriptions": [
] ]
@ -116,6 +130,53 @@
"surfaceGenTag": "empty", "surfaceGenTag": "empty",
"heightOffset": 0 "heightOffset": 0
} }
},
{
"id": "plains_rock",
"displayName": "Plains (rock)",
"isAerial": false,
"isSurface": true,
"isSubterranean": false,
"regions": [
{
"frequency": 1.0,
"baseFloorVoxel": 1,
"floorVariants": [
{
"voxelId": 7,
"frequency": 0.5,
"dispersion": 0.5,
"priority": 1.0
},
{
"voxelId": 8,
"frequency": 0.5,
"dispersion": 0.5,
"priority": 1.0
}
],
"foliageDescription": [
]
}
],
"surfaceGenerationParams": {
"surfaceGenTag": "plains",
"heightOffset": 10,
"floorVariants": [
{
"voxelId": 7,
"frequency": 0.5,
"dispersion": 0.5,
"priority": 1.0
},
{
"voxelId": 8,
"frequency": 0.5,
"dispersion": 0.5,
"priority": 1.0
}
]
}
} }
], ],
"files": [ "files": [

View File

@ -35,7 +35,7 @@ out vec3 samplerIndexVec; //the indices in the atlas of textures to sample
out vec3 samplerRatioVec; //the vector of HOW MUCH to pull from each texture in the atlas out vec3 samplerRatioVec; //the vector of HOW MUCH to pull from each texture in the atlas
float map(float value, float min1, float max1, float min2, float max2);
void main() { void main() {
//normalize posiiton and normal //normalize posiiton and normal
@ -48,6 +48,9 @@ void main() {
ViewFragPos = vec3(view * model * FinalVertex); ViewFragPos = vec3(view * model * FinalVertex);
Normal = mat3(transpose(inverse(model))) * aNormal; Normal = mat3(transpose(inverse(model))) * aNormal;
// //clamp the aPos vector to just shy of its surrounding values
// //this prevents sampling across into the next texture
// vec3 clampedPos = vec3(map(aPos.x,0,1,0.02,0.98), map(aPos.y,0,1,0.02,0.98), map(aPos.z,0,1,0.02,0.98));
//reference https://catlikecoding.com/unity/tutorials/advanced-rendering/triplanar-mapping/ //reference https://catlikecoding.com/unity/tutorials/advanced-rendering/triplanar-mapping/
texPlane1 = aPos.zy * TEXTURE_MAP_SCALE; texPlane1 = aPos.zy * TEXTURE_MAP_SCALE;
texPlane2 = aPos.xz * TEXTURE_MAP_SCALE; texPlane2 = aPos.xz * TEXTURE_MAP_SCALE;
@ -71,3 +74,9 @@ void main() {
//set final position with opengl space //set final position with opengl space
gl_Position = projection * view * model * FinalVertex; gl_Position = projection * view * model * FinalVertex;
} }
float map(float value, float min1, float max1, float min2, float max2) {
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file #maven.buildNumber.plugin properties file
#Tue Apr 01 15:25:00 EDT 2025 #Wed Apr 02 13:31:25 EDT 2025
buildNumber=616 buildNumber=617

View File

@ -1411,6 +1411,10 @@ World creation options work
(04/02/2025) (04/02/2025)
Homogenous worlds actually generate-able Homogenous worlds actually generate-able
Two EXCELLENT rock textures Two EXCELLENT rock textures
Fix rock2 texture
biome floor elements controlling noise generator's voxel selection
Plains (rock) biome

View File

@ -107,5 +107,5 @@ public class BiomeData {
public BiomeSurfaceGenerationParams getSurfaceGenerationParams(){ public BiomeSurfaceGenerationParams getSurfaceGenerationParams(){
return surfaceGenerationParams; return surfaceGenerationParams;
} }
} }

View File

@ -1,9 +1,11 @@
package electrosphere.game.data.biome; package electrosphere.game.data.biome;
import electrosphere.util.noise.NoiseMapperElement;
/** /**
* Describes how a given voxel type may be used to populate the floor of the biome * Describes how a given voxel type may be used to populate the floor of the biome
*/ */
public class BiomeFloorElement { public class BiomeFloorElement implements NoiseMapperElement {
/** /**
* The id of the voxel type for this element in particular * The id of the voxel type for this element in particular
@ -25,4 +27,17 @@ public class BiomeFloorElement {
*/ */
Double priority; Double priority;
/**
* Gets the voxel id of this floor element
* @return The voxel id
*/
public int getVoxelId(){
return voxelId;
}
@Override
public float getFrequency() {
return (float)(double)this.frequency;
}
} }

View File

@ -4,6 +4,9 @@ import java.util.List;
import org.graalvm.polyglot.HostAccess.Export; import org.graalvm.polyglot.HostAccess.Export;
import electrosphere.util.annotation.Exclude;
import electrosphere.util.noise.NoiseMapper;
/** /**
* Params for the surface generation algorithm * Params for the surface generation algorithm
*/ */
@ -32,6 +35,19 @@ public class BiomeSurfaceGenerationParams {
@Export @Export
List<BiomeFoliageDescription> foliageDescriptions; List<BiomeFoliageDescription> foliageDescriptions;
/**
* Used to map gradients into floor variants (ie to distribute the floor variants spatially)
*/
@Exclude
NoiseMapper<BiomeFloorElement> floorVariantMapper;
/**
* Precomputes the surface voxel distribution
*/
protected void precomputeSurfaceDistribution(){
this.floorVariantMapper = new NoiseMapper<BiomeFloorElement>(floorVariants);
}
/** /**
* Gets the tag for the generation algorithm for generating the surface * Gets the tag for the generation algorithm for generating the surface
* @return The tag for the generation algorithm for generating the surface * @return The tag for the generation algorithm for generating the surface
@ -64,6 +80,13 @@ public class BiomeSurfaceGenerationParams {
return foliageDescriptions; return foliageDescriptions;
} }
/**
* Gets a floor variant based on a gradient value
* @param gradientValue The gradient value
* @return The floor element
*/
public BiomeFloorElement getFloorVariant(float gradientValue){
return this.floorVariantMapper.lookup(gradientValue);
}
} }

View File

@ -54,6 +54,7 @@ public class BiomeTypeMap {
idBiomeMap.put(id,biome); idBiomeMap.put(id,biome);
if(biome.isSurface()){ if(biome.isSurface()){
this.surfaceBiomes.add(biome); this.surfaceBiomes.add(biome);
biome.getSurfaceGenerationParams().precomputeSurfaceDistribution();
} }
if(biome.isAerial()){ if(biome.isAerial()){
this.skyBiomes.add(biome); this.skyBiomes.add(biome);
@ -61,8 +62,9 @@ public class BiomeTypeMap {
if(biome.isSubterranean()){ if(biome.isSubterranean()){
this.subterraneanBiomes.add(biome); this.subterraneanBiomes.add(biome);
} }
indexBiomeMap.put(indexBiomeMap.size(),biome); int index = indexBiomeMap.size();
biomeIndexMap.put(biome,indexBiomeMap.size()); indexBiomeMap.put(index,biome);
biomeIndexMap.put(biome,index);
} }
/** /**

View File

@ -183,6 +183,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
double surfaceHeight = heightfield[x][z]; double surfaceHeight = heightfield[x][z];
double gradient = gradientField[x][z]; double gradient = gradientField[x][z];
BiomeData surfaceBiome = surfaceBiomeMap[x][z]; BiomeData surfaceBiome = surfaceBiomeMap[x][z];
BiomeSurfaceGenerationParams surfaceParams = surfaceBiome.getSurfaceGenerationParams();
for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){ for(int y = 0; y < ServerTerrainChunk.CHUNK_DATA_GENERATOR_SIZE; y++){
int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION); int finalWorldY = worldY + ((y * strideValue) / ServerTerrainChunk.CHUNK_DIMENSION);
@ -196,7 +197,7 @@ public class TestGenerationChunkGenerator implements ChunkGenerator {
realX, realY, realZ, realX, realY, realZ,
stride, stride,
surfaceHeight, gradient, surfaceHeight, gradient,
surfaceBiome, surfaceBiome, surfaceParams,
generationContext generationContext
); );
if(voxel != null){ if(voxel != null){

View File

@ -2,6 +2,7 @@ package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData; import electrosphere.game.data.biome.BiomeData;
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel; import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext; import electrosphere.server.terrain.generation.interfaces.GenerationContext;
import io.github.studiorailgun.MathUtils; import io.github.studiorailgun.MathUtils;
@ -79,7 +80,7 @@ public class AnimeMountainsGen implements VoxelGenerator {
int chunkX, int chunkY, int chunkZ, int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ, double realX, double realY, double realZ,
int stride, double surfaceHeight, double surfaceGradient, int stride, double surfaceHeight, double surfaceGradient,
BiomeData surfaceBiome, BiomeData surfaceBiome, BiomeSurfaceGenerationParams surfaceParams,
GenerationContext generationContext GenerationContext generationContext
) { ) {
Globals.profiler.beginAggregateCpuSample("AnimeMountainsGen.getVoxel"); Globals.profiler.beginAggregateCpuSample("AnimeMountainsGen.getVoxel");

View File

@ -2,6 +2,7 @@ package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData; import electrosphere.game.data.biome.BiomeData;
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel; import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext; import electrosphere.server.terrain.generation.interfaces.GenerationContext;
@ -39,7 +40,7 @@ public class HillsVoxelGen implements VoxelGenerator {
double realX, double realY, double realZ, double realX, double realY, double realZ,
int stride, int stride,
double surfaceHeight, double surfaceGradient, double surfaceHeight, double surfaceGradient,
BiomeData surfaceBiome, BiomeData surfaceBiome, BiomeSurfaceGenerationParams surfaceParams,
GenerationContext generationContext GenerationContext generationContext
){ ){
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel"); Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");

View File

@ -2,6 +2,7 @@ package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.game.data.biome.BiomeData; import electrosphere.game.data.biome.BiomeData;
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel; import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext; import electrosphere.server.terrain.generation.interfaces.GenerationContext;
@ -45,7 +46,7 @@ public class MountainVoxelGen implements VoxelGenerator {
double realX, double realY, double realZ, double realX, double realY, double realZ,
int stride, int stride,
double surfaceHeight, double surfaceGradient, double surfaceHeight, double surfaceGradient,
BiomeData surfaceBiome, BiomeData surfaceBiome, BiomeSurfaceGenerationParams surfaceParams,
GenerationContext generationContext GenerationContext generationContext
){ ){
Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel"); Globals.profiler.beginAggregateCpuSample("HillsVoxelGen.getVoxel");

View File

@ -1,6 +1,8 @@
package electrosphere.server.terrain.generation.voxelphase; package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.game.data.biome.BiomeData; import electrosphere.game.data.biome.BiomeData;
import electrosphere.game.data.biome.BiomeFloorElement;
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
import electrosphere.game.data.voxel.sampler.SamplerFile; import electrosphere.game.data.voxel.sampler.SamplerFile;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel; import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext; import electrosphere.server.terrain.generation.interfaces.GenerationContext;
@ -62,7 +64,8 @@ public class NoiseVoxelGen implements VoxelGenerator {
int chunkX, int chunkY, int chunkZ, int chunkX, int chunkY, int chunkZ,
double realX, double realY, double realZ, double realX, double realY, double realZ,
int stride, double surfaceHeight, double surfaceGradient, int stride, double surfaceHeight, double surfaceGradient,
BiomeData surfaceBiome, GenerationContext generationContext BiomeData surfaceBiome, BiomeSurfaceGenerationParams surfaceParams,
GenerationContext generationContext
) { ) {
//floor handling //floor handling
@ -91,11 +94,13 @@ public class NoiseVoxelGen implements VoxelGenerator {
voxel.weight = -1.0f; voxel.weight = -1.0f;
voxel.type = 0; voxel.type = 0;
} else if(heightDiff < -strideMultiplier){ } else if(heightDiff < -strideMultiplier){
BiomeFloorElement floorEl = surfaceParams.getFloorVariant((float)surfaceGradient);
//generate full-size surface-type voxel //generate full-size surface-type voxel
double finalHeight = sample; double finalHeight = sample;
voxel.weight = (float)finalHeight; voxel.weight = (float)finalHeight;
voxel.type = 2; voxel.type = floorEl.getVoxelId();
} else { } else {
BiomeFloorElement floorEl = surfaceParams.getFloorVariant((float)surfaceGradient);
//surface //surface
double surfacePercent = -heightDiff / strideMultiplier; double surfacePercent = -heightDiff / strideMultiplier;
if(surfacePercent > 1.0 || surfacePercent < 0){ if(surfacePercent > 1.0 || surfacePercent < 0){
@ -103,7 +108,7 @@ public class NoiseVoxelGen implements VoxelGenerator {
} }
double finalHeight = sample * surfacePercent * 2 - 1; double finalHeight = sample * surfacePercent * 2 - 1;
voxel.weight = (float)(finalHeight * sample); voxel.weight = (float)(finalHeight * sample);
voxel.type = 2; voxel.type = floorEl.getVoxelId();
} }
} }

View File

@ -1,6 +1,7 @@
package electrosphere.server.terrain.generation.voxelphase; package electrosphere.server.terrain.generation.voxelphase;
import electrosphere.game.data.biome.BiomeData; import electrosphere.game.data.biome.BiomeData;
import electrosphere.game.data.biome.BiomeSurfaceGenerationParams;
import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel; import electrosphere.server.terrain.generation.interfaces.GeneratedVoxel;
import electrosphere.server.terrain.generation.interfaces.GenerationContext; import electrosphere.server.terrain.generation.interfaces.GenerationContext;
@ -37,6 +38,7 @@ public interface VoxelGenerator {
* @param surfaceHeight The height of the surface at x,z * @param surfaceHeight The height of the surface at x,z
* @param surfaceGradient The rate of change in the surface at this point * @param surfaceGradient The rate of change in the surface at this point
* @param surfaceBiome The surface biome of the chunk * @param surfaceBiome The surface biome of the chunk
* @param surfaceGenPArams Extra parameters for generating surface voxel values
* @param generationContext The generation context * @param generationContext The generation context
*/ */
public void getVoxel( public void getVoxel(
@ -46,7 +48,7 @@ public interface VoxelGenerator {
double realX, double realY, double realZ, double realX, double realY, double realZ,
int stride, int stride,
double surfaceHeight, double surfaceGradient, double surfaceHeight, double surfaceGradient,
BiomeData surfaceBiome, BiomeData surfaceBiome, BiomeSurfaceGenerationParams surfaceGenParams,
GenerationContext generationContext GenerationContext generationContext
); );

View File

@ -0,0 +1,76 @@
package electrosphere.util.noise;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Maps objects to a frequency, then allows normalized noise values to index into the frequency range
*/
public class NoiseMapper<T> {
/**
* The objects in the buckets
*/
List<T> objects;
/**
* The frequencies
*/
float[] frequencies;
public NoiseMapper(List<T> objects){
Map<NoiseMapperElement,T> typeMap = new HashMap<NoiseMapperElement,T>();
//convert types
List<NoiseMapperElement> elements = objects.stream().map(object -> {
if(object instanceof NoiseMapperElement){
NoiseMapperElement casted = (NoiseMapperElement)object;
typeMap.put(casted,object);
return casted;
} else {
throw new Error("Supplied a class that does not extend NoiseMapper! " + object.getClass());
}
}).collect(Collectors.toList());
//set frequencies
float frequencySum = 0;
for(NoiseMapperElement el : elements){
frequencySum = frequencySum + el.getFrequency();
}
this.frequencies = new float[elements.size()];
this.objects = new ArrayList<T>();
int i = 0;
float accumulator = 0;
for(NoiseMapperElement el : elements){
this.frequencies[i] = el.getFrequency() / frequencySum + accumulator;
this.objects.add(typeMap.get(el));
accumulator = accumulator + this.frequencies[i];
i++;
}
}
/**
* Looks up a value's corresponding object
* @param value The value
* @return The object
*/
public T lookup(float value){
if(value < 0){
throw new Error("Supplied value less than 0! " + value);
} else if(value > 1){
throw new Error("Supplied value greater than 1! " + value);
}
int searchIndex = 0;
float prevFreq = 0;
while(searchIndex < frequencies.length){
if(value >= prevFreq && value <= frequencies[searchIndex]){
return objects.get(searchIndex);
}
prevFreq = frequencies[searchIndex];
searchIndex++;
}
throw new Error("Failed to mape value " + value + " into object! " + frequencies + " " + objects);
}
}

View File

@ -0,0 +1,14 @@
package electrosphere.util.noise;
/**
* An element that can be supplied to a noise mapper
*/
public interface NoiseMapperElement {
/**
* Gets the frequency of this element
* @return The frequency
*/
public float getFrequency();
}