Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | Thummper |
Hi,
The biomes for my landscape are chosen by a shader depending on a value from a noise texture.
I want to be able to determine the biome of a point on my landscape outside of my shader as well, so I can place things like trees in the correct biomes.
My shader code is as follows:
shader_type spatial;
uniform sampler2D noise;
uniform sampler2D subnoise;
uniform sampler2D grass;
uniform sampler2D grassAlt;
uniform sampler2D dirt;
uniform float noiseZoom = 1000;
uniform float grassZoom = 10;
const float epsilon = 1e-4;
varying vec3 world_pos;
varying vec3 normal;
void vertex(){
// In vertex this position is local i think (not affected by camera)
world_pos = VERTEX;
normal = abs(NORMAL);
normal /= normal.x + normal.y + normal.z;
}
float inverseLerp(float a, float b, float value){
// Min, max, value
float val = (value - a) / (b - a);
return clamp(val, 0, 1);
}
void fragment() {
vec3 grCol = vec3(0.35, 0.63, 0.51);
vec3 gr2Col = vec3(0, 0.5, 0.5);
vec3 drCol = vec3(0.6, 0.46, 0.32);
float noiseValue = texture(noise, UV / noiseZoom).x;
float noisePercent = inverseLerp(0.0, 1.0, noiseValue);
float grassNoiseValue = texture(subnoise, UV / grassZoom).x;
float grassPercent = inverseLerp(0.0, 1.0, grassNoiseValue);
float g1 = clamp(sign(grassPercent - 0.0), 0.0, 1.0);
float g2 = clamp(sign(grassPercent - 0.5), 0.0, 1.0);
float grStrength = clamp(sign(noisePercent - 0.0), 0.0, 1.0);
float drStrength = clamp(sign(noisePercent - 0.5), 0.0, 1.0);
vec3 grassCol = (g1 * grCol) + (g2 * gr2Col);
ALBEDO = vec3(0, 0, 0);
ALBEDO = ((1.0 - grStrength) * ALBEDO) + (grStrength * grassCol);
ALBEDO = ((1.0 - drStrength) * ALBEDO) + (drStrength * drCol);
}
I have another function that is given an array of points that are on my mesh, it is as follows:
func interp(minimum, maximum, value):
var inVal = minimum + (maximum - minimum) * value
return clamp(minimum, maximum, inVal)
func generateTrees(gridPoints, biomeNoise, noiseZoom, minx, minz):
var biomeImage = biomeNoise.get_data()
var noise = biomeNoise.noise
var index = randi() % gridPoints.size()
for i in numberTrees:
var positionGood = false
var position
while positionGood == false:
# Pick a point from grid, if not used it is ok
index = randi() % gridPoints.size()
position = gridPoints[index]
var tempX = position.x / noiseZoom
var tempZ = position.z / noiseZoom
var noiseVal = interp(0, 1, noise.get_noise_2d(tempX, tempZ))
print("NoiseVal: ", noiseVal)
var drStrength = clamp(sign(noiseVal - 0.5), 0.0, 1.0);
print("drs: ", drStrength)
if !treePositions.has(position) && drStrength < 0.5:
positionGood = true
else:
fails += 1
if fails >= 5000:
setMultiMesh()
makeColliders()
return gridPoints
# We have a position
treePositions.push_back(position)
position.y -= 1.5
var type = randi() % treeMMs.size()
var tree = treeObject.new()
tree.init(type, position)
treeList.push_back(tree)
gridPoints.remove(index)
setMultiMesh()
makeColliders()
return gridPoints
Both my function and my shader are given the same noiseTexture and noiseZoom factors - but the noise value seems to be different in both instances.
I want to determine the dirtStrength outside of my shader and only draw trees if it is below a certain value (so only draw trees if it is not dirt)
Any ideas on how I can replicate the results of my shader in this function?
Well, I’m still stuck on this.
So my shader uses UV to sample a position from my noiseTexture.
These values are in the range (0,0) → (1,1).
Then these values are divided my by noiseZoom to essentially zoom in on the noise.
So the values texture uses are very very small, but it is still able to sample noise.
In my function outside of my shader, the grid points are just some vertices on my landscape mesh. These are generally in the range of like -210 → 210 as the center of my landscape is (0, 0).
I have tried to replicate the texture function outside of my shader by normalizing the coords so that they are in a range of (0, 0) → (1, 1) like the UV coords.
But I cannot sample from an image using get_pixel with floats. The coords are too small without even dividing by noiseZoom.
So I’ve been scaling these by the width and height of my noiseTexture (512 x 512) to get values that can be sampled from the texture image.
But the values that I sample from my image do not match up with the values sampled by my shader.
Even if I remove noiseZoom entirely, in my function outside of my shader, sampling from the image, or using get_noise_2d, does not result in values that match what my shader produce.
So I’m not sure how I should go about adding biomes to my terrain.
Thummper | 2020-08-15 13:56