Add wind to grass toping
This commit is contained in:
parent
ef89bd8c49
commit
9086a794a8
5 changed files with 30 additions and 6 deletions
|
|
@ -50,7 +50,7 @@ cbuffer VoxelCB : register(b0) {
|
||||||
uint chunkCount;
|
uint chunkCount;
|
||||||
uint bleedMask; // bit N set = material N can bleed onto neighbors
|
uint bleedMask; // bit N set = material N can bleed onto neighbors
|
||||||
uint resistBleedMask; // bit N set = material N resists bleed from neighbors
|
uint resistBleedMask; // bit N set = material N resists bleed from neighbors
|
||||||
uint _cullPad2;
|
float windTime; // elapsed time for wind animation (seconds)
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Indirect draw args (must match C++ IndirectDrawArgs, 20 bytes) ──
|
// ── Indirect draw args (must match C++ IndirectDrawArgs, 20 bytes) ──
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,24 @@ VSOutput main(uint vertexID : SV_VertexID, uint instanceID : SV_InstanceID) {
|
||||||
|
|
||||||
float3 worldPos = inst.worldPos + vtx.position;
|
float3 worldPos = inst.worldPos + vtx.position;
|
||||||
|
|
||||||
|
// ── Wind animation (vegetation only) ────────────────────────
|
||||||
|
// Height above the voxel face (y=1 in local space) drives amplitude.
|
||||||
|
// Quadratic scaling: base stays anchored, tips sway the most.
|
||||||
|
if (push.materialID != 3u) { // not stone
|
||||||
|
float localHeight = vtx.position.y - 1.0;
|
||||||
|
if (localHeight > 0.0) {
|
||||||
|
float heightFactor = localHeight * localHeight; // quadratic
|
||||||
|
float phase = worldPos.x * 1.8 + worldPos.z * 1.3 + windTime * 3.5;
|
||||||
|
float phase2 = worldPos.x * 0.7 - worldPos.z * 2.1 + windTime * 2.7;
|
||||||
|
float swayX = sin(phase) * 0.11 * heightFactor;
|
||||||
|
float swayZ = cos(phase2) * 0.08 * heightFactor;
|
||||||
|
float swayY = -abs(sin(phase * 0.7)) * 0.02 * heightFactor; // slight droop
|
||||||
|
worldPos.x += swayX;
|
||||||
|
worldPos.y += swayY;
|
||||||
|
worldPos.z += swayZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VSOutput output;
|
VSOutput output;
|
||||||
output.position = mul(viewProjection, float4(worldPos, 1.0));
|
output.position = mul(viewProjection, float4(worldPos, 1.0));
|
||||||
output.worldPos = worldPos;
|
output.worldPos = worldPos;
|
||||||
|
|
|
||||||
|
|
@ -399,7 +399,7 @@ void TopingSystem::generateGrassVariant(TopingDef& def, uint8_t bitmask) {
|
||||||
angle += (h1 - 0.5f) * 20.0f;
|
angle += (h1 - 0.5f) * 20.0f;
|
||||||
|
|
||||||
// Height: per-blade × per-tuft
|
// Height: per-blade × per-tuft
|
||||||
float bladeHeight = (0.06f + h2 * 0.28f) * tuftHeightScale;
|
float bladeHeight = (0.09f + h2 * 0.42f) * tuftHeightScale; // +50% height
|
||||||
|
|
||||||
float baseWidth = 0.030f + h3 * 0.030f;
|
float baseWidth = 0.030f + h3 * 0.030f;
|
||||||
float lean = (0.03f + h4 * 0.12f) * tuftLeanScale;
|
float lean = (0.03f + h4 * 0.12f) * tuftLeanScale;
|
||||||
|
|
@ -457,7 +457,7 @@ void TopingSystem::generateGrassVariant(TopingDef& def, uint8_t bitmask) {
|
||||||
float angle = (fanT - 0.5f) * 2.0f * 70.0f;
|
float angle = (fanT - 0.5f) * 2.0f * 70.0f;
|
||||||
angle += (h1 - 0.5f) * 15.0f;
|
angle += (h1 - 0.5f) * 15.0f;
|
||||||
|
|
||||||
float height = (0.10f + h2 * 0.22f) * cornerHeightScale;
|
float height = (0.15f + h2 * 0.33f) * cornerHeightScale; // +50% height
|
||||||
float baseWidth = 0.030f + h3 * 0.025f;
|
float baseWidth = 0.030f + h3 * 0.025f;
|
||||||
float lean = (0.04f + h4 * 0.10f) * cornerLeanScale;
|
float lean = (0.04f + h4 * 0.10f) * cornerLeanScale;
|
||||||
float midLean = 0.10f + h5 * 0.30f;
|
float midLean = 0.10f + h5 * 0.30f;
|
||||||
|
|
|
||||||
|
|
@ -714,7 +714,7 @@ void VoxelRenderer::render(
|
||||||
// Material IDs: 1=Grass, 2=Dirt, 3=Stone, 4=Sand, 5=Snow
|
// Material IDs: 1=Grass, 2=Dirt, 3=Stone, 4=Sand, 5=Snow
|
||||||
cb.bleedMask = (1u << 1) | (1u << 2) | (1u << 4) | (1u << 5); // Grass, Dirt, Sand, Snow can bleed (NOT Stone)
|
cb.bleedMask = (1u << 1) | (1u << 2) | (1u << 4) | (1u << 5); // Grass, Dirt, Sand, Snow can bleed (NOT Stone)
|
||||||
cb.resistBleedMask = (1u << 1); // Grass resists bleed (she bleeds onto others, not the reverse)
|
cb.resistBleedMask = (1u << 1); // Grass resists bleed (she bleeds onto others, not the reverse)
|
||||||
cb._cullPad2 = 0;
|
cb.windTime = windTime_;
|
||||||
dev->UpdateBuffer(&constantBuffer_, &cb, cmd, sizeof(cb));
|
dev->UpdateBuffer(&constantBuffer_, &cb, cmd, sizeof(cb));
|
||||||
|
|
||||||
// Render pass
|
// Render pass
|
||||||
|
|
@ -801,7 +801,7 @@ void VoxelRenderer::render(
|
||||||
cb.debugBlend = 0.0f;
|
cb.debugBlend = 0.0f;
|
||||||
cb.bleedMask = 0;
|
cb.bleedMask = 0;
|
||||||
cb.resistBleedMask = 0;
|
cb.resistBleedMask = 0;
|
||||||
cb._cullPad2 = 0;
|
cb.windTime = windTime_;
|
||||||
cb.chunkCount = chunkCount_;
|
cb.chunkCount = chunkCount_;
|
||||||
extractFrustumPlanes(vpMatrix, cb.frustumPlanes);
|
extractFrustumPlanes(vpMatrix, cb.frustumPlanes);
|
||||||
dev->UpdateBuffer(&constantBuffer_, &cb, cmd, sizeof(cb));
|
dev->UpdateBuffer(&constantBuffer_, &cb, cmd, sizeof(cb));
|
||||||
|
|
@ -1466,6 +1466,8 @@ void VoxelRenderPath::Update(float dt) {
|
||||||
float instantFps = (dt > 0.0f) ? (1.0f / dt) : 0.0f;
|
float instantFps = (dt > 0.0f) ? (1.0f / dt) : 0.0f;
|
||||||
smoothFps_ = smoothFps_ * 0.95f + instantFps * 0.05f;
|
smoothFps_ = smoothFps_ * 0.95f + instantFps * 0.05f;
|
||||||
if (camera) handleInput(dt);
|
if (camera) handleInput(dt);
|
||||||
|
windTime_ += dt;
|
||||||
|
renderer.windTime_ = windTime_;
|
||||||
|
|
||||||
// Animated terrain: regenerate at 60 Hz with time-shifted noise
|
// Animated terrain: regenerate at 60 Hz with time-shifted noise
|
||||||
// Fused: regenerate + pack voxel data in the same parallel pass
|
// Fused: regenerate + pack voxel data in the same parallel pass
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public:
|
||||||
|
|
||||||
bool debugFaceColors_ = false;
|
bool debugFaceColors_ = false;
|
||||||
bool debugBlend_ = false;
|
bool debugBlend_ = false;
|
||||||
|
float windTime_ = 0.0f; // set by VoxelRenderPath::Update each frame
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createPipeline();
|
void createPipeline();
|
||||||
|
|
@ -137,7 +138,7 @@ private:
|
||||||
uint32_t chunkCount;
|
uint32_t chunkCount;
|
||||||
uint32_t bleedMask; // bit N set = material N can bleed onto neighbors
|
uint32_t bleedMask; // bit N set = material N can bleed onto neighbors
|
||||||
uint32_t resistBleedMask; // bit N set = material N resists bleed from neighbors
|
uint32_t resistBleedMask; // bit N set = material N resists bleed from neighbors
|
||||||
uint32_t _cullPad2;
|
float windTime;
|
||||||
};
|
};
|
||||||
wi::graphics::GPUBuffer constantBuffer_;
|
wi::graphics::GPUBuffer constantBuffer_;
|
||||||
|
|
||||||
|
|
@ -236,6 +237,9 @@ private:
|
||||||
mutable float lastDt_ = 0.016f;
|
mutable float lastDt_ = 0.016f;
|
||||||
mutable float smoothFps_ = 60.0f;
|
mutable float smoothFps_ = 60.0f;
|
||||||
|
|
||||||
|
// Wind animation (continuous, always running)
|
||||||
|
float windTime_ = 0.0f;
|
||||||
|
|
||||||
// Animated terrain (wave effect at 60 Hz, toggled with F3)
|
// Animated terrain (wave effect at 60 Hz, toggled with F3)
|
||||||
bool animatedTerrain_ = false;
|
bool animatedTerrain_ = false;
|
||||||
float animTime_ = 0.0f;
|
float animTime_ = 0.0f;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue