mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-20 11:34:53 +02:00
Copy the textures of the terrain layers again when the season or the weather changes
This commit is contained in:
@@ -7417,11 +7417,18 @@ void opengl46_renderer::Update(double const Deltatime)
|
||||
Global.Season
|
||||
};
|
||||
std::swap( m_simulationstate, simulationstate );
|
||||
bool changed { false };
|
||||
if( ( m_simulationstate.season != simulationstate.season ) && ( false == simulationstate.season.empty() ) ) {
|
||||
m_materials.on_season_change();
|
||||
changed = true;
|
||||
}
|
||||
if( ( m_simulationstate.weather != simulationstate.weather ) && ( false == simulationstate.weather.empty() ) ) {
|
||||
m_materials.on_weather_change();
|
||||
changed = true;
|
||||
}
|
||||
if( changed ) {
|
||||
// the heightmap terrain keeps copies of the textures of its layer materials
|
||||
m_terrainmaterials.on_environment_change();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
namespace
|
||||
{
|
||||
|
||||
std::size_t constexpr max_layers{8};
|
||||
int constexpr initial_capacity{8};
|
||||
int constexpr copy_attempts{600}; // frames to wait for the textures of a layer to load before it's left with what it has
|
||||
float constexpr default_repeat{8.f};
|
||||
@@ -124,6 +123,15 @@ void opengl46_terrain_materials::make_storage(texture_array &Array, int const La
|
||||
texture.data_components = GL_RGBA;
|
||||
}
|
||||
|
||||
void opengl46_terrain_materials::read_material(layer &Layer)
|
||||
{
|
||||
auto const &material{m_materials.material(Layer.material)};
|
||||
Layer.repeat = (Layer.size > 0.f ? Layer.size : (material.size.x > 0.f ? material.size.x : default_repeat));
|
||||
Layer.normalmap = (material.shader && material.shader->texture_conf.count("normalmap") > 0);
|
||||
Layer.specgloss = (material.shader && material.shader->texture_conf.count("specgloss") > 0);
|
||||
Layer.reflection = (std::isfinite(material.params[1].z) ? material.params[1].z : 0.f);
|
||||
}
|
||||
|
||||
int opengl46_terrain_materials::layer_index(gfx::terrain_layer const &Layer)
|
||||
{
|
||||
for (auto const &existing : m_layers)
|
||||
@@ -134,14 +142,7 @@ int opengl46_terrain_materials::layer_index(gfx::terrain_layer const &Layer)
|
||||
entry.material = Layer.material;
|
||||
entry.size = Layer.size;
|
||||
entry.index = static_cast<int>(m_layers.size());
|
||||
auto const &material{m_materials.material(Layer.material)};
|
||||
entry.repeat = (Layer.size > 0.f ? Layer.size : (material.size.x > 0.f ? material.size.x : default_repeat));
|
||||
if (material.shader)
|
||||
{
|
||||
entry.normalmap = material.shader->texture_conf.count("normalmap") > 0;
|
||||
entry.specgloss = material.shader->texture_conf.count("specgloss") > 0;
|
||||
}
|
||||
entry.reflection = (std::isfinite(material.params[1].z) ? material.params[1].z : 0.f);
|
||||
read_material(entry);
|
||||
m_layers.push_back(entry);
|
||||
m_pending = true;
|
||||
|
||||
@@ -279,28 +280,62 @@ material_handle opengl46_terrain_materials::make(material_handle const Reuse, st
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, side, side, 0, GL_RGBA, GL_UNSIGNED_BYTE, texels.data());
|
||||
::glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
entry.count = count;
|
||||
entry.layers = indices;
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
entry.rotations[i] = Layers[i].rotation;
|
||||
write_table(entry);
|
||||
|
||||
auto &material{m_materials.material(entry.material)};
|
||||
material.params[2] = glm::vec4(Placement.x, Placement.y, 1.f / std::max(1.f, Placement.z), static_cast<float>(side - 1));
|
||||
return entry.material;
|
||||
}
|
||||
|
||||
void opengl46_terrain_materials::write_table(slot const &Slot)
|
||||
{
|
||||
// what the layers are: index in the arrays, repeat, which maps they have, reflection
|
||||
std::array<float, max_layers * 2 * 4> table{};
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
for (std::size_t i = 0; i < Slot.count; ++i)
|
||||
{
|
||||
auto const &layer{m_layers[indices[i]]};
|
||||
auto const &layer{m_layers[Slot.layers[i]]};
|
||||
table[i * 4 + 0] = static_cast<float>(layer.index);
|
||||
table[i * 4 + 1] = 1.f / std::max(0.01f, layer.repeat);
|
||||
table[i * 4 + 2] = layer.normalmap ? 1.f : 0.f;
|
||||
table[i * 4 + 3] = layer.specgloss ? 1.f : 0.f;
|
||||
table[(max_layers + i) * 4 + 0] = layer.reflection;
|
||||
// the textures turned by the layer of the chunk (the same material can be turned differently in another layer)
|
||||
auto const angle{glm::radians(static_cast<double>(Layers[i].rotation))};
|
||||
auto const angle{glm::radians(static_cast<double>(Slot.rotations[i]))};
|
||||
table[(max_layers + i) * 4 + 1] = static_cast<float>(std::cos(angle));
|
||||
table[(max_layers + i) * 4 + 2] = static_cast<float>(std::sin(angle));
|
||||
}
|
||||
bind_for_upload(m_textures.texture(entry.table));
|
||||
bind_for_upload(m_textures.texture(Slot.table));
|
||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, static_cast<GLsizei>(max_layers), 2, 0, GL_RGBA, GL_FLOAT, table.data());
|
||||
opengl_texture::reset_unit_cache();
|
||||
}
|
||||
|
||||
auto &material{m_materials.material(entry.material)};
|
||||
material.params[2] = glm::vec4(Placement.x, Placement.y, 1.f / std::max(1.f, Placement.z), static_cast<float>(side - 1));
|
||||
return entry.material;
|
||||
void opengl46_terrain_materials::on_environment_change()
|
||||
{
|
||||
if (m_state <= 0)
|
||||
return;
|
||||
bool changed{false};
|
||||
for (auto &layer : m_layers)
|
||||
{
|
||||
auto const &material{m_materials.material(layer.material)};
|
||||
if (false == (material.update_on_season_change || material.update_on_weather_change))
|
||||
continue;
|
||||
// the reloaded material can have other textures, other maps and another size
|
||||
read_material(layer);
|
||||
layer.copied = false;
|
||||
layer.attempts = 0;
|
||||
changed = true;
|
||||
}
|
||||
if (false == changed)
|
||||
return;
|
||||
m_pending = true;
|
||||
// the tables of the chunks hold what the layers have, freed slots get theirs anew when they're used again
|
||||
for (auto const &entry : m_slots)
|
||||
if (entry.used)
|
||||
write_table(entry);
|
||||
}
|
||||
|
||||
void opengl46_terrain_materials::release(material_handle const Material)
|
||||
|
||||
@@ -33,8 +33,12 @@ class opengl46_terrain_materials
|
||||
void release(material_handle const Material);
|
||||
// copies the textures of new layers into the arrays; to be called before the frame is drawn
|
||||
void update();
|
||||
// the layer materials which change with the season or the weather were reloaded, their textures are copied again
|
||||
void on_environment_change();
|
||||
|
||||
private:
|
||||
static constexpr std::size_t max_layers{8};
|
||||
|
||||
struct layer
|
||||
{
|
||||
material_handle material{null_handle};
|
||||
@@ -60,12 +64,18 @@ class opengl46_terrain_materials
|
||||
std::array<texture_handle, 2> weights{null_handle, null_handle};
|
||||
texture_handle table{null_handle};
|
||||
bool used{false};
|
||||
// what the table was made of, kept to make it again when a layer changes
|
||||
std::size_t count{0};
|
||||
std::array<int, max_layers> layers{};
|
||||
std::array<float, max_layers> rotations{};
|
||||
};
|
||||
|
||||
bool init();
|
||||
texture_handle make_texture(std::string const &Name, GLenum const Target);
|
||||
void make_storage(texture_array &Array, int const Layers);
|
||||
void read_material(layer &Layer);
|
||||
int layer_index(gfx::terrain_layer const &Layer);
|
||||
void write_table(slot const &Slot);
|
||||
bool copy_layer(layer &Layer);
|
||||
std::size_t acquire_slot(material_handle const Reuse);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user