terrain generator: grass length, texture target resolution
This commit is contained in:
+39
-14
@@ -274,7 +274,7 @@ void TerrainWindow::Create(EditorComponent* _editor)
|
||||
ClearTransform();
|
||||
|
||||
wi::gui::Window::Create(ICON_TERRAIN " Terrain", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE);
|
||||
SetSize(XMFLOAT2(420, 860));
|
||||
SetSize(XMFLOAT2(420, 900));
|
||||
|
||||
closeButton.SetTooltip("Delete Terrain.\nThis will bake generated virtual textures to static textures which could take a while!");
|
||||
OnClose([=](wi::gui::EventArgs args) {
|
||||
@@ -303,11 +303,13 @@ void TerrainWindow::Create(EditorComponent* _editor)
|
||||
terrain->SetGrassEnabled(grassCheckBox.GetCheck());
|
||||
terrain->lod_multiplier = lodSlider.GetValue();
|
||||
terrain->texlod = texlodSlider.GetValue();
|
||||
terrain->target_texture_resolution = (uint32_t)texResolutionSlider.GetValue();
|
||||
terrain->generation = (int)generationSlider.GetValue();
|
||||
terrain->prop_generation = (int)propGenerationSlider.GetValue();
|
||||
terrain->physics_generation = (int)physicsGenerationSlider.GetValue();
|
||||
terrain->prop_density = propDensitySlider.GetValue();
|
||||
terrain->grass_density = grassDensitySlider.GetValue();
|
||||
terrain->grass_length = grassLengthSlider.GetValue();
|
||||
terrain->chunk_scale = scaleSlider.GetValue();
|
||||
terrain->seed = (uint32_t)seedSlider.GetValue();
|
||||
terrain->bottomLevel = bottomLevelSlider.GetValue();
|
||||
@@ -390,6 +392,15 @@ void TerrainWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&texlodSlider);
|
||||
|
||||
texResolutionSlider.Create(256, 4096, 1024, 4096 - 256, "Tex Resolution: ");
|
||||
texResolutionSlider.SetTooltip("Virtual texture target resolution for most detailed chunk.\nNote: if chunk resolution is bigger than texture resolution, texture scaling will be applied to those chunks.");
|
||||
texResolutionSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
texResolutionSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
texResolutionSlider.OnSlide([this](wi::gui::EventArgs args) {
|
||||
terrain->target_texture_resolution = (uint32_t)args.iValue;
|
||||
});
|
||||
AddWidget(&texResolutionSlider);
|
||||
|
||||
generationSlider.Create(0, 16, 12, 16, "Generation Distance: ");
|
||||
generationSlider.SetTooltip("How far out chunks will be generated (value is in number of chunks)");
|
||||
generationSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
@@ -426,7 +437,7 @@ void TerrainWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&propDensitySlider);
|
||||
|
||||
grassDensitySlider.Create(0, 4, 1, 1000, "Grass Density: ");
|
||||
grassDensitySlider.Create(0, 4, 2, 1000, "Grass Density: ");
|
||||
grassDensitySlider.SetTooltip("Modifies overall grass density.");
|
||||
grassDensitySlider.SetSize(XMFLOAT2(wid, hei));
|
||||
grassDensitySlider.SetPos(XMFLOAT2(x, y += step));
|
||||
@@ -435,6 +446,15 @@ void TerrainWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&grassDensitySlider);
|
||||
|
||||
grassLengthSlider.Create(0, 8, 2, 1000, "Grass Length: ");
|
||||
grassLengthSlider.SetTooltip("Modifies overall grass length.");
|
||||
grassLengthSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
grassLengthSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
grassLengthSlider.OnSlide([this](wi::gui::EventArgs args) {
|
||||
terrain->grass_properties.length = args.fValue;
|
||||
});
|
||||
AddWidget(&grassLengthSlider);
|
||||
|
||||
presetCombo.Create("Preset: ");
|
||||
presetCombo.SetTooltip("Select a terrain preset");
|
||||
presetCombo.SetSize(XMFLOAT2(wid, hei));
|
||||
@@ -769,10 +789,13 @@ void TerrainWindow::SetEntity(Entity entity)
|
||||
physicsCheckBox.SetCheck(terrain->IsPhysicsEnabled());
|
||||
lodSlider.SetValue(terrain->lod_multiplier);
|
||||
texlodSlider.SetValue(terrain->texlod);
|
||||
texResolutionSlider.SetValue((float)terrain->target_texture_resolution);
|
||||
generationSlider.SetValue((float)terrain->generation);
|
||||
propGenerationSlider.SetValue((float)terrain->prop_generation);
|
||||
physicsGenerationSlider.SetValue((float)terrain->physics_generation);
|
||||
propDensitySlider.SetValue(terrain->prop_density);
|
||||
grassDensitySlider.SetValue(terrain->grass_density);
|
||||
grassLengthSlider.SetValue(terrain->grass_properties.length);
|
||||
scaleSlider.SetValue(terrain->chunk_scale);
|
||||
seedSlider.SetValue((float)terrain->seed);
|
||||
bottomLevelSlider.SetValue(terrain->bottomLevel);
|
||||
@@ -847,7 +870,7 @@ void TerrainWindow::SetupAssets()
|
||||
terrain_preset.material_HighAltitude.textures[MaterialComponent::NORMALMAP].name = "terrain/high_altitude_nor.jpg";
|
||||
terrain_preset.material_GrassParticle.textures[MaterialComponent::BASECOLORMAP].name = "terrain/grassparticle.png";
|
||||
terrain_preset.material_GrassParticle.alphaRef = 0.75f;
|
||||
terrain_preset.grass_properties.length = 5;
|
||||
terrain_preset.grass_properties.length = 2;
|
||||
terrain_preset.grass_properties.frameCount = 2;
|
||||
terrain_preset.grass_properties.framesX = 1;
|
||||
terrain_preset.grass_properties.framesY = 2;
|
||||
@@ -866,16 +889,16 @@ void TerrainWindow::SetupAssets()
|
||||
{
|
||||
wi::terrain::Prop& prop = terrain_preset.props.emplace_back();
|
||||
prop.min_count_per_chunk = 0;
|
||||
prop.max_count_per_chunk = 10;
|
||||
prop.max_count_per_chunk = 20;
|
||||
prop.region = 0;
|
||||
prop.region_power = 2;
|
||||
prop.noise_frequency = 0.1f;
|
||||
prop.noise_power = 1;
|
||||
prop.threshold = 0.4f;
|
||||
prop.min_size = 2.0f;
|
||||
prop.max_size = 8.0f;
|
||||
prop.min_y_offset = -0.5f;
|
||||
prop.max_y_offset = -0.5f;
|
||||
prop.min_size = 1.0f;
|
||||
prop.max_size = 4.0f;
|
||||
prop.min_y_offset = -0.25f;
|
||||
prop.max_y_offset = -0.25f;
|
||||
Entity mesh_entity = props_scene.Entity_FindByName("tree_mesh");
|
||||
props_scene.impostors.Create(mesh_entity).swapInDistance = 200;
|
||||
Entity object_entity = props_scene.Entity_FindByName("tree_object");
|
||||
@@ -908,9 +931,9 @@ void TerrainWindow::SetupAssets()
|
||||
prop.noise_power = 2;
|
||||
prop.threshold = 0.5f;
|
||||
prop.min_size = 0.02f;
|
||||
prop.max_size = 4.0f;
|
||||
prop.min_y_offset = -2;
|
||||
prop.max_y_offset = 0.5f;
|
||||
prop.max_size = 2.0f;
|
||||
prop.min_y_offset = -1;
|
||||
prop.max_y_offset = 0.25f;
|
||||
Entity mesh_entity = props_scene.Entity_FindByName("rock_mesh");
|
||||
Entity object_entity = props_scene.Entity_FindByName("rock_object");
|
||||
ObjectComponent* object = props_scene.objects.GetComponent(object_entity);
|
||||
@@ -942,9 +965,9 @@ void TerrainWindow::SetupAssets()
|
||||
prop.noise_frequency = 0.01f;
|
||||
prop.noise_power = 4;
|
||||
prop.threshold = 0.1f;
|
||||
prop.min_size = 0.1f;
|
||||
prop.max_size = 1.5f;
|
||||
prop.min_y_offset = -1;
|
||||
prop.min_size = 0.05f;
|
||||
prop.max_size = 0.5f;
|
||||
prop.min_y_offset = -0.25;
|
||||
prop.max_y_offset = 0;
|
||||
Entity mesh_entity = props_scene.Entity_FindByName("bush_mesh");
|
||||
Entity object_entity = props_scene.Entity_FindByName("bush_object");
|
||||
@@ -1032,11 +1055,13 @@ void TerrainWindow::ResizeLayout()
|
||||
physicsCheckBox.SetPos(XMFLOAT2(grassCheckBox.GetPos().x - 100, grassCheckBox.GetPos().y));
|
||||
add(lodSlider);
|
||||
add(texlodSlider);
|
||||
add(texResolutionSlider);
|
||||
add(generationSlider);
|
||||
add(propGenerationSlider);
|
||||
add(physicsGenerationSlider);
|
||||
add(propDensitySlider);
|
||||
add(grassDensitySlider);
|
||||
add(grassLengthSlider);
|
||||
add(presetCombo);
|
||||
add(scaleSlider);
|
||||
add(seedSlider);
|
||||
|
||||
@@ -58,11 +58,13 @@ public:
|
||||
wi::gui::CheckBox physicsCheckBox;
|
||||
wi::gui::Slider lodSlider;
|
||||
wi::gui::Slider texlodSlider;
|
||||
wi::gui::Slider texResolutionSlider;
|
||||
wi::gui::Slider generationSlider;
|
||||
wi::gui::Slider propGenerationSlider;
|
||||
wi::gui::Slider physicsGenerationSlider;
|
||||
wi::gui::Slider propDensitySlider;
|
||||
wi::gui::Slider grassDensitySlider;
|
||||
wi::gui::Slider grassLengthSlider;
|
||||
wi::gui::ComboBox presetCombo;
|
||||
wi::gui::Slider scaleSlider;
|
||||
wi::gui::Slider seedSlider;
|
||||
|
||||
@@ -42,7 +42,8 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
tex.GetDimensions(dim.x, dim.y);
|
||||
float2 diff = dim / output_dim;
|
||||
float lod = log2(max(diff.x, diff.y));
|
||||
float4 baseColorMap = tex.SampleLevel(sampler_linear_clamp, uv, lod);
|
||||
float2 overscale = lod < 0 ? diff : 1;
|
||||
float4 baseColorMap = tex.SampleLevel(sampler_linear_wrap, uv / overscale, lod);
|
||||
baseColor *= baseColorMap;
|
||||
}
|
||||
total_baseColor += baseColor * weight;
|
||||
@@ -56,7 +57,8 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
tex.GetDimensions(dim.x, dim.y);
|
||||
float2 diff = dim / output_dim;
|
||||
float lod = log2(max(diff.x, diff.y));
|
||||
float4 surfaceMap = tex.SampleLevel(sampler_linear_clamp, uv, lod);
|
||||
float2 overscale = lod < 0 ? diff : 1;
|
||||
float4 surfaceMap = tex.SampleLevel(sampler_linear_wrap, uv / overscale, lod);
|
||||
surface *= surfaceMap;
|
||||
}
|
||||
total_surface += surface * weight;
|
||||
@@ -70,7 +72,8 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
tex.GetDimensions(dim.x, dim.y);
|
||||
float2 diff = dim / output_dim;
|
||||
float lod = log2(max(diff.x, diff.y));
|
||||
float2 normalMap = tex.SampleLevel(sampler_linear_clamp, uv, lod).rg;
|
||||
float2 overscale = lod < 0 ? diff : 1;
|
||||
float2 normalMap = tex.SampleLevel(sampler_linear_wrap, uv / overscale, lod).rg;
|
||||
normal = normalMap;
|
||||
}
|
||||
total_normal += normal * weight;
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace wi::scene
|
||||
wi::ecs::ComponentManager<ScriptComponent>& scripts = componentLibrary.Register<ScriptComponent>("wi::scene::Scene::scripts");
|
||||
wi::ecs::ComponentManager<ExpressionComponent>& expressions = componentLibrary.Register<ExpressionComponent>("wi::scene::Scene::expressions");
|
||||
wi::ecs::ComponentManager<HumanoidComponent>& humanoids = componentLibrary.Register<HumanoidComponent>("wi::scene::Scene::humanoids");
|
||||
wi::ecs::ComponentManager<wi::terrain::Terrain>& terrains = componentLibrary.Register<wi::terrain::Terrain>("wi::scene::Scene::terrains", 1); // version = 1
|
||||
wi::ecs::ComponentManager<wi::terrain::Terrain>& terrains = componentLibrary.Register<wi::terrain::Terrain>("wi::scene::Scene::terrains", 2); // version = 2
|
||||
|
||||
// Non-serialized attributes:
|
||||
float dt = 0;
|
||||
|
||||
@@ -308,7 +308,7 @@ namespace wi::terrain
|
||||
virtual_texture_barriers_end.clear();
|
||||
|
||||
// Check whether there are any materials that would write to virtual textures:
|
||||
uint32_t max_texture_resolution = 0;
|
||||
bool virtual_texture_any = false;
|
||||
bool virtual_texture_available[MaterialComponent::TEXTURESLOT_COUNT] = {};
|
||||
virtual_texture_available[MaterialComponent::SURFACEMAP] = true; // this is always needed to bake individual material properties
|
||||
MaterialComponent* virtual_materials[4] = {
|
||||
@@ -329,9 +329,7 @@ namespace wi::terrain
|
||||
if (material->textures[i].resource.IsValid())
|
||||
{
|
||||
virtual_texture_available[i] = true;
|
||||
const TextureDesc& desc = material->textures[i].resource.GetTexture().GetDesc();
|
||||
max_texture_resolution = std::max(max_texture_resolution, desc.width);
|
||||
max_texture_resolution = std::max(max_texture_resolution, desc.height);
|
||||
virtual_texture_any = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -384,14 +382,15 @@ namespace wi::terrain
|
||||
}
|
||||
}
|
||||
|
||||
// Grass density modification:
|
||||
if (chunk_data.grass_entity != INVALID_ENTITY && std::abs(chunk_data.grass_density_current - grass_density) > std::numeric_limits<float>::epsilon())
|
||||
// Grass property update:
|
||||
if (chunk_data.grass_entity != INVALID_ENTITY)
|
||||
{
|
||||
wi::HairParticleSystem* grass = scene->hairs.GetComponent(chunk_data.grass_entity);
|
||||
if (grass != nullptr)
|
||||
{
|
||||
chunk_data.grass_density_current = grass_density;
|
||||
grass->strandCount = uint32_t(chunk_data.grass.strandCount * chunk_data.grass_density_current);
|
||||
grass->length = grass_properties.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +441,7 @@ namespace wi::terrain
|
||||
}
|
||||
|
||||
// Collect virtual texture update requests:
|
||||
if (max_texture_resolution > 0)
|
||||
if (virtual_texture_any)
|
||||
{
|
||||
uint32_t texture_lod = 0;
|
||||
const float distsq = wi::math::DistanceSquared(camera.Eye, chunk_data.sphere.center);
|
||||
@@ -459,7 +458,8 @@ namespace wi::terrain
|
||||
texture_lod = uint32_t(dist_to_sphere * texlodMultiplier);
|
||||
}
|
||||
|
||||
chunk_data.required_texture_resolution = uint32_t(max_texture_resolution / std::pow(2.0f, (float)std::max(0u, texture_lod)));
|
||||
chunk_data.required_texture_resolution = uint32_t(target_texture_resolution / std::pow(2.0f, (float)std::max(0u, texture_lod)));
|
||||
chunk_data.required_texture_resolution = AlignTo(chunk_data.required_texture_resolution, 8u);
|
||||
chunk_data.required_texture_resolution = std::max(8u, chunk_data.required_texture_resolution);
|
||||
MaterialComponent* material = scene->materials.GetComponent(chunk_data.entity);
|
||||
|
||||
@@ -935,7 +935,7 @@ namespace wi::terrain
|
||||
case MaterialComponent::BASECOLORMAP:
|
||||
case MaterialComponent::SURFACEMAP:
|
||||
case MaterialComponent::NORMALMAP:
|
||||
if (!tex.name.empty() && tex.GetGPUResource() != nullptr)
|
||||
if (tex.GetGPUResource() != nullptr)
|
||||
{
|
||||
wi::vector<uint8_t> filedata;
|
||||
if (wi::helper::saveTextureToMemory(tex.resource.GetTexture(), filedata))
|
||||
@@ -1032,6 +1032,10 @@ namespace wi::terrain
|
||||
{
|
||||
archive >> physics_generation;
|
||||
}
|
||||
if (seri.GetVersion() >= 2)
|
||||
{
|
||||
archive >> target_texture_resolution;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
archive >> count;
|
||||
@@ -1180,6 +1184,10 @@ namespace wi::terrain
|
||||
{
|
||||
archive << physics_generation;
|
||||
}
|
||||
if (seri.GetVersion() >= 2)
|
||||
{
|
||||
archive << target_texture_resolution;
|
||||
}
|
||||
|
||||
archive << props.size();
|
||||
for (size_t i = 0; i < props.size(); ++i)
|
||||
|
||||
@@ -140,6 +140,7 @@ namespace wi::terrain
|
||||
int physics_generation = 3;
|
||||
float prop_density = 1;
|
||||
float grass_density = 1;
|
||||
float grass_length = 1;
|
||||
float chunk_scale = 1;
|
||||
uint32_t seed = 3926;
|
||||
float bottomLevel = -60;
|
||||
@@ -147,6 +148,7 @@ namespace wi::terrain
|
||||
float region1 = 1;
|
||||
float region2 = 2;
|
||||
float region3 = 8;
|
||||
uint32_t target_texture_resolution = 1024;
|
||||
|
||||
wi::vector<std::shared_ptr<Modifier>> modifiers;
|
||||
wi::vector<Modifier*> modifiers_to_remove;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wi::version
|
||||
// minor features, major updates, breaking compatibility changes
|
||||
const int minor = 71;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 55;
|
||||
const int revision = 56;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user