mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-06 09:03:52 +00:00
feat(editor): gradient texture blend for biome transitions
- Gradient Blend: smoothly transitions base texture from one biome to another across the entire tile (horizontal or vertical) - Preset buttons: Grass→Sand and Grass→Snow gradients - Creates natural biome transition zones without manual painting - Alpha blending from 0% to 100% across 16 chunks
This commit is contained in:
parent
0907bb5ca2
commit
0a6e54e8a2
3 changed files with 55 additions and 0 deletions
|
|
@ -897,6 +897,26 @@ void EditorUI::renderTexturePaintPanel(EditorApp& app) {
|
|||
selectedTexture_.c_str());
|
||||
|
||||
// Auto-paint by height
|
||||
if (ImGui::CollapsingHeader("Gradient Blend")) {
|
||||
static int gradDir = 0;
|
||||
ImGui::RadioButton("Horizontal##grad", &gradDir, 0);
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("Vertical##grad", &gradDir, 1);
|
||||
if (ImGui::Button("Grass → Sand Gradient", ImVec2(-1, 0))) {
|
||||
app.getTexturePainter().gradientBlend(
|
||||
"Tileset\\Elwynn\\ElwynnGrassBase.blp",
|
||||
"Tileset\\Tanaris\\TanarisSandBase01.blp", gradDir == 0);
|
||||
app.showToast("Gradient applied");
|
||||
}
|
||||
if (ImGui::Button("Grass → Snow Gradient", ImVec2(-1, 0))) {
|
||||
app.getTexturePainter().gradientBlend(
|
||||
"Tileset\\Elwynn\\ElwynnGrassBase.blp",
|
||||
"Tileset\\Expansion02\\Dragonblight\\DragonblightFreshSmoothSnowA.blp", gradDir == 0);
|
||||
app.showToast("Gradient applied");
|
||||
}
|
||||
ImGui::TextColored(ImVec4(0.6f,0.6f,0.6f,1), "Smooth texture transition across tile");
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Auto-Paint by Slope")) {
|
||||
static float slopeThresh = 0.4f;
|
||||
ImGui::SliderFloat("Slope Threshold", &slopeThresh, 0.1f, 0.9f);
|
||||
|
|
|
|||
|
|
@ -289,6 +289,38 @@ void TexturePainter::paintAlongPath(const glm::vec3& start, const glm::vec3& end
|
|||
}
|
||||
}
|
||||
|
||||
void TexturePainter::gradientBlend(const std::string& tex1, const std::string& tex2, bool horizontal) {
|
||||
if (!terrain_) return;
|
||||
uint32_t id1 = ensureTextureInList(tex1);
|
||||
uint32_t id2 = ensureTextureInList(tex2);
|
||||
|
||||
for (int ci = 0; ci < 256; ci++) {
|
||||
auto& chunk = terrain_->chunks[ci];
|
||||
if (!chunk.hasHeightMap() || chunk.layers.empty()) continue;
|
||||
int cx = ci % 16, cy = ci / 16;
|
||||
|
||||
// Set base texture to tex1
|
||||
chunk.layers[0].textureId = id1;
|
||||
|
||||
// Add tex2 as blended layer
|
||||
int layerIdx = ensureLayerOnChunk(ci, id2);
|
||||
if (layerIdx < 0) continue;
|
||||
size_t off = chunk.layers[layerIdx].offsetMCAL;
|
||||
if (off + 4096 > chunk.alphaMap.size()) continue;
|
||||
|
||||
for (int ty = 0; ty < 64; ty++) {
|
||||
for (int tx = 0; tx < 64; tx++) {
|
||||
float t;
|
||||
if (horizontal)
|
||||
t = (cx * 64.0f + tx) / (16.0f * 64.0f);
|
||||
else
|
||||
t = (cy * 64.0f + ty) / (16.0f * 64.0f);
|
||||
chunk.alphaMap[off + ty * 64 + tx] = static_cast<uint8_t>(t * 255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> TexturePainter::erase(const glm::vec3& center, float radius,
|
||||
float strength, float falloff) {
|
||||
if (!terrain_ || activeTexture_.empty()) return {};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ public:
|
|||
void paintAlongPath(const glm::vec3& start, const glm::vec3& end,
|
||||
float width, const std::string& texturePath);
|
||||
|
||||
// Gradient blend: transitions base texture from one to another across tile
|
||||
void gradientBlend(const std::string& tex1, const std::string& tex2, bool horizontal);
|
||||
|
||||
// Paint the active texture at the given world position
|
||||
// Returns list of modified chunk indices
|
||||
std::vector<int> paint(const glm::vec3& center, float radius, float strength, float falloff);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue