Skip to content

Commit

Permalink
[Wind] Vegetation wil not sway at the point of contact with the groun…
Browse files Browse the repository at this point in the history
…d, and it will achieve full sway going at it's top
  • Loading branch information
PanosK92 committed Oct 25, 2023
1 parent 9431304 commit 8974215
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 79 deletions.
2 changes: 1 addition & 1 deletion data/shaders/common_buffers.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ struct MaterialBufferData
float anisotropic_rotation;
float sheen;
float sheen_tint;
float padding3;
float world_space_height;
};

cbuffer BufferFrame : register(b0) { FrameBufferData buffer_frame; }; // low frequency - updates once per frame
Expand Down
9 changes: 6 additions & 3 deletions data/shaders/common_vertex_operations.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//===============================

// this function is shared between depth_prepass.hlsl and g_buffer.hlsl, this is because the calculations have to be exactly the same

float4 compute_screen_space_position(Vertex_PosUvNorTan input, uint instance_id, matrix transform, matrix view_projection)
{
float4 position = input.position;
Expand All @@ -33,8 +32,12 @@ float4 compute_screen_space_position(Vertex_PosUvNorTan input, uint instance_id,
float4 world_position = mul(position, transform);

#if INSTANCED
world_position = mul(world_position, input.instance_transform);
world_position = vertex_simulation::wind::apply(instance_id, world_position, buffer_frame.time);
matrix instance = input.instance_transform;
world_position = mul(world_position, instance);
if (material_vertex_animate_wind())
{
world_position = vertex_simulation::wind::apply(instance_id, world_position, float3(instance._41, instance._42, instance._43), buffer_frame.time);
}
#endif

if (material_vertex_animate_water())
Expand Down
25 changes: 7 additions & 18 deletions data/shaders/g_buffer.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,15 @@ PixelInputType mainVS(Vertex_PosUvNorTan input, uint instance_id : SV_InstanceID
{
PixelInputType output;

// position current
output.position = compute_screen_space_position(input, instance_id, buffer_pass.transform, buffer_frame.view_projection);
output.position_ss_current = output.position;

// position previous
float4 position_world_previous = mul(input.position, pass_get_transform_previous());
#if INSTANCED
position_world_previous = mul(position_world_previous, input.instance_transform);
position_world_previous = vertex_simulation::wind::apply(instance_id, position_world_previous, buffer_frame.time - buffer_frame.delta_time);
#endif
if (material_vertex_animate_water())
{
position_world_previous = vertex_simulation::wave::apply(position_world_previous, buffer_frame.time - buffer_frame.delta_time);
}
output.position_ss_previous = mul(position_world_previous, buffer_frame.view_projection_previous);

// misc
// position
output.position = compute_screen_space_position(input, instance_id, buffer_pass.transform, buffer_frame.view_projection);
output.position_ss_current = output.position;
output.position_ss_previous = compute_screen_space_position(input, instance_id, pass_get_transform_previous(), buffer_frame.view_projection_previous);
// normals
output.normal_world = normalize(mul(input.normal, (float3x3)buffer_pass.transform)).xyz;
output.tangent_world = normalize(mul(input.tangent, (float3x3)buffer_pass.transform)).xyz;
output.uv = input.uv;
// uv
output.uv = input.uv;

return output;
}
Expand Down
48 changes: 24 additions & 24 deletions data/shaders/vertex_simulation.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// wind
static const float3 wind_direction = float3(1, 0, 0);
static const float wind_vertex_sway_extent = 0.08f; // oscillation amplitude
static const float wind_vertex_sway_speed = 4.0f; // oscillation frequency
static const float wind_vertex_sway_extent = 0.1f; // oscillation amplitude
static const float wind_vertex_sway_speed = 4.0f; // oscillation frequency

// wave
static const float wave_height = 0.15f;
static const float wave_height = 0.2f;
static const float wave_frequency = 10.0f;
static const float wave_speed = 0.5f;
static const float3 wave_direction = float3(1.0f, 0.0f, 0.0f);
Expand All @@ -50,42 +50,42 @@ struct vertex_simulation
return lerp(hash(i), hash(i + 1.0), f);
}

static float4 apply(uint instance_id, float4 world_position, float time)
static float4 apply(uint instance_id, float4 position_vertex, float3 position_transform, float time)
{
if (material_vertex_animate_wind())
{
// base sine wave
float phase_offset = float(instance_id) * 0.1f;
float base_wave = sin((time * wind_vertex_sway_speed) + world_position.x + phase_offset);
// base wave
float phase_offset = float(instance_id) * PI_HALF;
float base_wave1 = sin((time * wind_vertex_sway_speed) + position_vertex.x + phase_offset);
float base_wave2 = sin((time * wind_vertex_sway_speed * 0.8f) + position_vertex.x + phase_offset + PI_HALF); // out of phase

// additional Perlin noise
float noise_factor = perlin_noise(world_position.x * 0.1f + time) - 0.5f;
// perlin noise
float noise_factor = perlin_noise(position_vertex.x * 0.1f + time) - 0.5f;

// combine multiple frequencies
float combined_wave = base_wave + 0.5 * sin((time * wind_vertex_sway_speed * 1.5f) + world_position.x + phase_offset);
// combine base waves with noise
float combined_wave = (base_wave1 + base_wave2) * 0.5f + noise_factor;

// calculate final offset
float3 offset = wind_direction * (combined_wave + noise_factor) * wind_vertex_sway_extent;
// don't sway at the bottom of the mesh, sway the most at the top
float sway_factor = saturate((position_vertex.y - position_transform.y) / buffer_material.world_space_height);

// calculate final offset
float3 offset = wind_direction * (combined_wave + noise_factor) * wind_vertex_sway_extent * sway_factor;

world_position.xyz += offset;
}

return world_position;
position_vertex.xyz += offset;
return position_vertex;
}
};

struct wave
{
// gerstner waves

static float4 apply(float4 world_position, float time)
static float4 apply(float4 position_vertex, float time)
{
// gerstner wave equation
float k = PI2 / wave_frequency;
float w = sqrt(9.8f / k) * wave_speed;

// phase and amplitude
float phase = dot(wave_direction, world_position.xz) * k + time * w;
float phase = dot(wave_direction, position_vertex.xz) * k + time * w;
float c = cos(phase);
float s = sin(phase);

Expand All @@ -95,10 +95,10 @@ struct vertex_simulation
offset.z = wave_height * wave_direction.z * c;
offset.y = wave_height * s;

world_position.xz += offset.xz;
world_position.y += offset.y;
position_vertex.xz += offset.xz;
position_vertex.y += offset.y;

return world_position;
return position_vertex;
}
};
};
2 changes: 2 additions & 0 deletions runtime/Rendering/Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace Spartan
{
case MaterialProperty::CanBeEdited: return "can_be_edited";
case MaterialProperty::SingleTextureRoughnessMetalness: return "single_texture_roughness_metalness";
case MaterialProperty::WorldSpaceHeight: return "world_space_height";
case MaterialProperty::Clearcoat: return "clearcoat_multiplier";
case MaterialProperty::Clearcoat_Roughness: return "clearcoat_roughness_multiplier";
case MaterialProperty::Anisotropic: return "anisotropic_multiplier";
Expand Down Expand Up @@ -94,6 +95,7 @@ namespace Spartan
SetProperty(MaterialProperty::MultiplierRoughness, 1.0f);
SetProperty(MaterialProperty::TextureTilingX, 1.0f);
SetProperty(MaterialProperty::TextureTilingY, 1.0f);
SetProperty(MaterialProperty::WorldSpaceHeight, 1.0f);
}

bool Material::LoadFromFile(const std::string& file_path)
Expand Down
3 changes: 2 additions & 1 deletion runtime/Rendering/Material.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace Spartan
{
CanBeEdited,
SingleTextureRoughnessMetalness,
WorldSpaceHeight, // height of the mesh the material is applied to
Clearcoat, // extra white specular layer on top of others
Clearcoat_Roughness, // roughness of clearcoat specular
Anisotropic, // amount of anisotropy for specular reflection
Expand Down Expand Up @@ -107,6 +108,6 @@ namespace Spartan

private:
std::array<std::shared_ptr<RHI_Texture>, 11> m_textures;
std::array<float, 25> m_properties;
std::array<float, 26> m_properties;
};
}
3 changes: 2 additions & 1 deletion runtime/Rendering/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ namespace Spartan
if (!renderable)
return 0.0f;

return (renderable->GetAabb().GetCenter() - camera->GetTransform()->GetPosition()).LengthSquared();
return (renderable->GetBoundingBox().GetCenter() - camera->GetTransform()->GetPosition()).LengthSquared();
};

// sort by depth
Expand Down Expand Up @@ -565,6 +565,7 @@ namespace Spartan
m_cb_material_cpu.properties = 0;

// set
m_cb_material_cpu.world_space_height = material->GetProperty(MaterialProperty::WorldSpaceHeight);
m_cb_material_cpu.color.x = material->GetProperty(MaterialProperty::ColorR);
m_cb_material_cpu.color.y = material->GetProperty(MaterialProperty::ColorG);
m_cb_material_cpu.color.z = material->GetProperty(MaterialProperty::ColorB);
Expand Down
5 changes: 3 additions & 2 deletions runtime/Rendering/Renderer_ConstantBuffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ namespace Spartan
float anisitropic_rotation = 0.0f;
float sheen = 0.0f;
float sheen_tint = 0.0f;
float padding = 0.0f;
float world_space_height = 0.0f;

bool operator==(const Cb_Material& rhs) const
{
Expand All @@ -176,7 +176,8 @@ namespace Spartan
anisotropic == rhs.anisotropic &&
anisitropic_rotation == rhs.anisitropic_rotation &&
sheen == rhs.sheen &&
sheen_tint == rhs.sheen_tint;
sheen_tint == rhs.sheen_tint &&
world_space_height == rhs.world_space_height;
}
};

Expand Down
6 changes: 3 additions & 3 deletions runtime/Rendering/Renderer_Primitives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,22 +341,22 @@ namespace Spartan
}
}

// AABBs
// bounding boxes
if (GetOption<bool>(Renderer_Option::Debug_Aabb))
{
for (const auto& entity : GetEntities()[Renderer_Entity::Geometry])
{
if (auto renderable = entity->GetComponent<Renderable>())
{
DrawBox(renderable->GetAabb(), Vector4(0.41f, 0.86f, 1.0f, 1.0f));
DrawBox(renderable->GetBoundingBox(), Vector4(0.41f, 0.86f, 1.0f, 1.0f));
}
}

for (const auto& entity : GetEntities()[Renderer_Entity::GeometryTransparent])
{
if (auto renderable = entity->GetComponent<Renderable>())
{
DrawBox(renderable->GetAabb(), Vector4(0.41f, 0.86f, 1.0f, 1.0f));
DrawBox(renderable->GetBoundingBox(), Vector4(0.41f, 0.86f, 1.0f, 1.0f));
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions runtime/World/Components/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ namespace Spartan

bool Camera::IsInViewFrustum(shared_ptr<Renderable> renderable) const
{
const BoundingBox& box = renderable->GetAabb();
const BoundingBox& box = renderable->GetBoundingBox();
const Vector3 center = box.GetCenter();
const Vector3 extents = box.GetExtents();

Expand Down Expand Up @@ -195,7 +195,7 @@ namespace Spartan
continue;

// Get object oriented bounding box
const BoundingBox& aabb = entity->GetComponent<Renderable>()->GetAabb();
const BoundingBox& aabb = entity->GetComponent<Renderable>()->GetBoundingBox();

// Compute hit distance
float distance = m_ray.HitDistance(aabb);
Expand Down Expand Up @@ -620,7 +620,7 @@ namespace Spartan
// ...otherwise we apply a simple offset so that the rotation vector doesn't suffer
if (shared_ptr<Renderable> renderable = entity->GetComponent<Renderable>())
{
m_lerp_to_target_position -= target_direction * renderable->GetAabb().GetExtents().Length() * 2.0f;
m_lerp_to_target_position -= target_direction * renderable->GetBoundingBox().GetExtents().Length() * 2.0f;
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion runtime/World/Components/Light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ namespace Spartan

bool Light::IsInViewFrustum(shared_ptr<Renderable> renderable, uint32_t index) const
{
const auto box = renderable->GetAabb();
const auto box = renderable->GetBoundingBox();
const auto center = box.GetCenter();
const auto extents = box.GetExtents();

Expand Down
2 changes: 1 addition & 1 deletion runtime/World/Components/ReflectionProbe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ namespace Spartan

bool ReflectionProbe::IsInViewFrustum(shared_ptr<Renderable> renderable, uint32_t index) const
{
const auto box = renderable->GetAabb();
const auto box = renderable->GetBoundingBox();
const auto center = box.GetCenter();
const auto extents = box.GetExtents();

Expand Down
25 changes: 15 additions & 10 deletions runtime/World/Components/Renderable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace Spartan
SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_geometry_vertex_offset, uint32_t);
SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_geometry_vertex_count, uint32_t);
SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_mesh, Mesh*);
SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_bounding_box_local, BoundingBox);
SP_REGISTER_ATTRIBUTE_VALUE_VALUE(m_bounding_box_mesh, BoundingBox);
}

Renderable::~Renderable()
Expand All @@ -61,7 +61,7 @@ namespace Spartan
stream->Write(m_geometry_index_count);
stream->Write(m_geometry_vertex_offset);
stream->Write(m_geometry_vertex_count);
stream->Write(m_bounding_box_local);
stream->Write(m_bounding_box_mesh);
stream->Write(m_mesh ? m_mesh->GetObjectName() : "");

// material
Expand All @@ -80,7 +80,7 @@ namespace Spartan
m_geometry_index_count = stream->ReadAs<uint32_t>();
m_geometry_vertex_offset = stream->ReadAs<uint32_t>();
m_geometry_vertex_count = stream->ReadAs<uint32_t>();
stream->Read(&m_bounding_box_local);
stream->Read(&m_bounding_box_mesh);
string model_name;
stream->Read(&model_name);
m_mesh = ResourceCache::GetByName<Mesh>(model_name).get();
Expand Down Expand Up @@ -108,7 +108,7 @@ namespace Spartan
)
{
m_mesh = mesh;
m_bounding_box_local = aabb;
m_bounding_box_mesh = aabb;
m_geometry_index_offset = index_offset;
m_geometry_index_count = index_count;
m_geometry_vertex_offset = vertex_offset;
Expand All @@ -127,14 +127,14 @@ namespace Spartan
m_geometry_vertex_count = m_mesh->GetVertexCount();
}

if (m_bounding_box_local == BoundingBox::Undefined)
if (m_bounding_box_mesh == BoundingBox::Undefined)
{
m_bounding_box_local = m_mesh->GetAabb();
m_bounding_box_mesh = m_mesh->GetAabb();
}

SP_ASSERT(m_geometry_index_count != 0);
SP_ASSERT(m_geometry_vertex_count != 0);
SP_ASSERT(m_bounding_box_local != BoundingBox::Undefined);
SP_ASSERT(m_bounding_box_mesh != BoundingBox::Undefined);
}

void Renderable::SetGeometry(const Renderer_MeshType mesh_type)
Expand All @@ -148,19 +148,19 @@ namespace Spartan
m_mesh->GetGeometry(m_geometry_index_offset, m_geometry_index_count, m_geometry_vertex_offset, m_geometry_vertex_count, indices, vertices);
}

const BoundingBox& Renderable::GetAabb()
const BoundingBox& Renderable::GetBoundingBox()
{
// either the bounding box is dirty, or the transform has changed, or the instances have changed
if (m_bounding_box_dirty || m_last_transform != GetTransform()->GetMatrix())
{
m_bounding_box = m_bounding_box_local.Transform(GetTransform()->GetMatrix());
m_bounding_box = m_bounding_box_mesh.Transform(GetTransform()->GetMatrix());

// loop through each instance and expand the bounding box
for (const Matrix& instance_transform : m_instances)
{
// the instance transforms are transposed (see terrain.cpp), so we need to transpose them back
Matrix transposed = instance_transform.Transposed();
m_bounding_box.Merge(m_bounding_box_local.Transform(Matrix::CreateTranslation(transposed.GetTranslation())));
m_bounding_box.Merge(m_bounding_box_mesh.Transform(Matrix::CreateTranslation(transposed.GetTranslation())));
}

m_last_transform = GetTransform()->GetMatrix();
Expand All @@ -171,6 +171,11 @@ namespace Spartan
}


const Spartan::Math::BoundingBox Renderable::GetBoundingBoxNoInstancing()
{
return m_bounding_box_mesh.Transform(GetTransform()->GetMatrix());
}

shared_ptr<Material> Renderable::SetMaterial(const shared_ptr<Material>& material)
{
SP_ASSERT(material != nullptr);
Expand Down
Loading

0 comments on commit 8974215

Please sign in to comment.