mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-05 16:43:52 +00:00
feat(editor): procedural noise generator, sky presets, viewport lighting
- Noise Generator in Sculpt panel: applies procedural value noise with configurable frequency, amplitude, octaves, and seed to create hills/valleys across entire tile instantly - Sky/Lighting presets: View > Sky menu with Day (blue sky, high sun), Dusk (orange, low sun), Night (dark blue, moonlight) - Viewport clear color and light direction now configurable at runtime - Noise uses smoothstep interpolation with octave fractal layering
This commit is contained in:
parent
f5fe9a0101
commit
42749e9b58
7 changed files with 108 additions and 2 deletions
|
|
@ -124,7 +124,9 @@ void EditorApp::run() {
|
|||
rpInfo.renderArea.extent = vkCtx->getSwapchainExtent();
|
||||
|
||||
VkClearValue clearValues[4]{};
|
||||
clearValues[0].color = {{0.15f, 0.15f, 0.2f, 1.0f}};
|
||||
float cr, cg, cb;
|
||||
viewport_.getClearColor(cr, cg, cb);
|
||||
clearValues[0].color = {{cr, cg, cb, 1.0f}};
|
||||
clearValues[1].depthStencil = {1.0f, 0};
|
||||
rpInfo.clearValueCount = 2;
|
||||
rpInfo.pClearValues = clearValues;
|
||||
|
|
@ -594,6 +596,23 @@ void EditorApp::requestQuit() {
|
|||
window_->setShouldClose(true);
|
||||
}
|
||||
|
||||
void EditorApp::setSkyPreset(int preset) {
|
||||
switch (preset) {
|
||||
case 0: // Day
|
||||
viewport_.setClearColor(0.4f, 0.6f, 0.9f);
|
||||
viewport_.setLightDir(glm::normalize(glm::vec3(0.5f, -1.0f, 0.8f)));
|
||||
break;
|
||||
case 1: // Dusk
|
||||
viewport_.setClearColor(0.6f, 0.3f, 0.2f);
|
||||
viewport_.setLightDir(glm::normalize(glm::vec3(0.8f, -0.3f, 0.1f)));
|
||||
break;
|
||||
case 2: // Night
|
||||
viewport_.setClearColor(0.05f, 0.05f, 0.12f);
|
||||
viewport_.setLightDir(glm::normalize(glm::vec3(0.2f, -0.5f, 0.8f)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorApp::startGizmoMode(TransformMode mode) {
|
||||
auto& giz = viewport_.getGizmo();
|
||||
giz.setMode(mode);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ public:
|
|||
|
||||
void startGizmoMode(TransformMode mode);
|
||||
void setGizmoAxis(TransformAxis axis);
|
||||
void setSkyPreset(int preset); // 0=day, 1=dusk, 2=night
|
||||
void snapSelectedToGround();
|
||||
|
||||
// Multi-tile support
|
||||
|
|
|
|||
|
|
@ -101,6 +101,13 @@ void EditorUI::renderMenuBar(EditorApp& app) {
|
|||
if (ImGui::MenuItem("Wireframe", "F3", &wf)) app.setWireframe(wf);
|
||||
if (ImGui::MenuItem("Reset Camera")) app.resetCamera();
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginMenu("Sky / Lighting")) {
|
||||
if (ImGui::MenuItem("Day")) app.setSkyPreset(0);
|
||||
if (ImGui::MenuItem("Dusk")) app.setSkyPreset(1);
|
||||
if (ImGui::MenuItem("Night")) app.setSkyPreset(2);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Save Bookmark", "F5")) app.saveBookmark("");
|
||||
auto& bmarks = app.getBookmarks();
|
||||
if (!bmarks.empty() && ImGui::BeginMenu("Load Bookmark")) {
|
||||
|
|
@ -230,6 +237,24 @@ void EditorUI::renderBrushPanel(EditorApp& app) {
|
|||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Set target height from cursor position");
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ImGui::CollapsingHeader("Noise Generator")) {
|
||||
static float noiseFreq = 0.005f;
|
||||
static float noiseAmp = 20.0f;
|
||||
static int noiseOctaves = 4;
|
||||
static int noiseSeed = 42;
|
||||
ImGui::SliderFloat("Frequency", &noiseFreq, 0.001f, 0.05f, "%.4f");
|
||||
ImGui::SliderFloat("Amplitude", &noiseAmp, 1.0f, 200.0f, "%.0f");
|
||||
ImGui::SliderInt("Octaves", &noiseOctaves, 1, 8);
|
||||
ImGui::InputInt("Seed", &noiseSeed);
|
||||
if (ImGui::Button("Apply Noise", ImVec2(-1, 0))) {
|
||||
app.getTerrainEditor().applyNoise(noiseFreq, noiseAmp, noiseOctaves,
|
||||
static_cast<uint32_t>(noiseSeed));
|
||||
}
|
||||
ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1),
|
||||
"Adds procedural hills/valleys to entire tile");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Terrain Holes (cave entrances):");
|
||||
auto& brush = app.getTerrainEditor().brush();
|
||||
|
|
|
|||
|
|
@ -568,7 +568,7 @@ void EditorViewport::updatePerFrameUBO() {
|
|||
data.view = camera_->getViewMatrix();
|
||||
data.projection = camera_->getProjectionMatrix();
|
||||
data.lightSpaceMatrix = glm::mat4(1.0f);
|
||||
data.lightDir = glm::vec4(glm::normalize(glm::vec3(0.5f, -1.0f, 0.3f)), 0.0f);
|
||||
data.lightDir = glm::vec4(lightDir_, 0.0f);
|
||||
data.lightColor = glm::vec4(1.0f, 0.95f, 0.85f, 0.0f);
|
||||
data.ambientColor = glm::vec4(0.3f, 0.3f, 0.35f, 0.0f);
|
||||
data.viewPos = glm::vec4(camera_->getPosition(), 0.0f);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ public:
|
|||
void setWireframe(bool enabled);
|
||||
bool isWireframe() const { return wireframe_; }
|
||||
|
||||
void setClearColor(float r, float g, float b) { clearR_=r; clearG_=g; clearB_=b; }
|
||||
void getClearColor(float& r, float& g, float& b) const { r=clearR_; g=clearG_; b=clearB_; }
|
||||
void setLightDir(const glm::vec3& d) { lightDir_ = d; }
|
||||
glm::vec3 getLightDir() const { return lightDir_; }
|
||||
|
||||
rendering::TerrainRenderer* getTerrainRenderer() { return terrainRenderer_.get(); }
|
||||
|
||||
private:
|
||||
|
|
@ -85,6 +90,8 @@ private:
|
|||
VkSampler shadowSampler_ = VK_NULL_HANDLE;
|
||||
|
||||
bool wireframe_ = false;
|
||||
float clearR_ = 0.15f, clearG_ = 0.15f, clearB_ = 0.2f;
|
||||
glm::vec3 lightDir_ = glm::normalize(glm::vec3(0.5f, -1.0f, 0.3f));
|
||||
|
||||
// Ghost preview state
|
||||
std::string ghostModelPath_;
|
||||
|
|
|
|||
|
|
@ -586,6 +586,57 @@ void TerrainEditor::removeWater(const glm::vec3& center, float radius) {
|
|||
}
|
||||
}
|
||||
|
||||
void TerrainEditor::applyNoise(float frequency, float amplitude, int octaves, uint32_t seed) {
|
||||
if (!terrain_) return;
|
||||
|
||||
// Simple value noise with octaves
|
||||
auto hash2d = [](int x, int y, uint32_t s) -> float {
|
||||
uint32_t h = static_cast<uint32_t>(x * 374761393 + y * 668265263 + s * 1274126177);
|
||||
h = (h ^ (h >> 13)) * 1274126177;
|
||||
h = h ^ (h >> 16);
|
||||
return static_cast<float>(h & 0xFFFF) / 65535.0f * 2.0f - 1.0f;
|
||||
};
|
||||
|
||||
auto smoothNoise = [&](float fx, float fy, uint32_t s) -> float {
|
||||
int ix = static_cast<int>(std::floor(fx));
|
||||
int iy = static_cast<int>(std::floor(fy));
|
||||
float fracX = fx - ix;
|
||||
float fracY = fy - iy;
|
||||
// Smoothstep
|
||||
fracX = fracX * fracX * (3.0f - 2.0f * fracX);
|
||||
fracY = fracY * fracY * (3.0f - 2.0f * fracY);
|
||||
float v00 = hash2d(ix, iy, s);
|
||||
float v10 = hash2d(ix + 1, iy, s);
|
||||
float v01 = hash2d(ix, iy + 1, s);
|
||||
float v11 = hash2d(ix + 1, iy + 1, s);
|
||||
float i0 = v00 + (v10 - v00) * fracX;
|
||||
float i1 = v01 + (v11 - v01) * fracX;
|
||||
return i0 + (i1 - i0) * fracY;
|
||||
};
|
||||
|
||||
for (int ci = 0; ci < 256; ci++) {
|
||||
auto& chunk = terrain_->chunks[ci];
|
||||
if (!chunk.hasHeightMap()) continue;
|
||||
int cx = ci % 16, cy = ci / 16;
|
||||
|
||||
for (int v = 0; v < 145; v++) {
|
||||
glm::vec3 wpos = chunkVertexWorldPos(ci, v);
|
||||
|
||||
float total = 0.0f;
|
||||
float amp = amplitude;
|
||||
float freq = frequency;
|
||||
for (int o = 0; o < octaves; o++) {
|
||||
total += smoothNoise(wpos.x * freq, wpos.y * freq, seed + o * 97) * amp;
|
||||
freq *= 2.0f;
|
||||
amp *= 0.5f;
|
||||
}
|
||||
chunk.heightMap.heights[v] += total;
|
||||
}
|
||||
dirtyChunks_.push_back(ci);
|
||||
}
|
||||
dirty_ = true;
|
||||
}
|
||||
|
||||
void TerrainEditor::punchHole(const glm::vec3& center, float radius) {
|
||||
if (!terrain_) return;
|
||||
auto affected = getAffectedChunks(center, radius);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ public:
|
|||
// Recalculate normals for modified chunks (improves lighting after sculpt)
|
||||
void recalcNormals(const std::vector<int>& chunkIndices);
|
||||
|
||||
// Noise generator: applies procedural height noise to the terrain
|
||||
void applyNoise(float frequency, float amplitude, int octaves, uint32_t seed);
|
||||
|
||||
// Water editing
|
||||
void setWaterLevel(const glm::vec3& center, float radius, float waterHeight, uint16_t liquidType = 0);
|
||||
void removeWater(const glm::vec3& center, float radius);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue