载入中...
搜索中...
未找到
SurfaceFluidRenderData.cpp
浏览该文件的文档.
2
3#include <glm/gtx/norm.hpp>
4
5#include <algorithm>
6#include <cmath>
7
8namespace eve::fluids {
9
11 const SurfaceDropletSimulation& simulation,
14 droplets_.clear();
15 droplets_.reserve(simulation.droplets().size());
16 const float stretch = std::max(0.f, params.velocityStretch);
17 const float maximumAspect = std::max(1.f, params.maxAspectRatio);
18 const float theta = glm::radians(std::clamp(
19 simulation.params().contactAngleDegrees, 5.f, 175.f));
20
21 for (const SurfaceDroplet& droplet : simulation.droplets()) {
22 const SurfaceSample surface = binding.evaluate(droplet.location, 0.f);
23 const float radius = simulation.dropletRadius(droplet.volume);
24 const float speed = glm::length(droplet.relativeVelocity);
25 const float aspect = std::clamp(1.f + speed * stretch, 1.f, maximumAspect);
26 const float axisScale = std::sqrt(aspect);
27
28 glm::vec3 direction = droplet.relativeVelocity;
29 direction -= surface.normal * glm::dot(direction, surface.normal);
30 if (glm::length2(direction) > 1e-12f)
31 direction = glm::normalize(direction);
32 else
33 direction = surface.tangent;
34 glm::vec3 across = glm::cross(surface.normal, direction);
35 if (glm::length2(across) > 1e-12f)
36 across = glm::normalize(across);
37 else
38 across = surface.bitangent;
39
41 instance.id = droplet.id;
42 instance.position = surface.position + surface.normal * std::max(0.f, params.surfaceOffset);
43 instance.normal = surface.normal;
44 instance.majorAxis = direction * (radius * axisScale);
45 instance.minorAxis = across * (radius / axisScale);
46 instance.velocity = surface.velocity + droplet.relativeVelocity;
47 instance.capHeight = radius * std::tan(theta * 0.5f);
48 instance.wetness = wetness ? std::clamp(wetness->sample(droplet.location), 0.f, 1.f) : 0.f;
49 droplets_.push_back(instance);
50 }
51}
52
56 sample.wetness = std::clamp(wetness, 0.f, 1.f);
57 const float response = sample.wetness * sample.wetness * (3.f - 2.f * sample.wetness);
58 sample.roughness = glm::mix(params.dryRoughness, params.wetRoughness, response);
59 sample.specular = glm::mix(params.drySpecular, params.wetSpecular, response);
60 sample.darkening = std::max(0.f, params.wetDarkening) * response;
61 sample.normalStrength = std::max(0.f, params.normalStrength) * response;
62 return sample;
63}
64
65} // namespace eve::fluids
float wetness
HexVec3 across
eve::action::ActionVfxBinding binding
float radius
RoadLaneDirection direction
Dynamic triangle surface used to bind films and droplets to deforming meshes.
CPU reference solver for droplets moving over static, rigid or deforming surfaces.
const std::vector< SurfaceDroplet > & droplets() const
Droplets.
float dropletRadius(float volume) const
Droplet radius.
void update(const FluidSurfaceBinding &binding, const SurfaceDropletSimulation &simulation, const SurfaceWetnessField *wetness=nullptr, const SurfaceFluidRenderParams &params={})
Rebuild attached droplet instances from the latest simulation pose.
static WetSurfaceMaterialSample evaluateMaterial(float wetness, const WetSurfaceMaterialParams &params={})
Evaluate wet PBR values from a normalized wetness input.
Lightweight material-space wet-film field stored at mesh vertices.
std::vector< ParamSpec > params
GLSL compute kernels for the GPU surface-flow solver.
Definition FluidTarget.h:12
float contactAngleDegrees
Water contact angle in degrees, used to derive a visible cap radius.
World-space oriented cap instance consumed by droplet instancing shaders.
One droplet addressed in material space on a dynamic triangle surface.
Tuning for converting simulated droplets into render instances.
Evaluated world-space frame and motion at a surface location.
Material mapping from simulated wetness to a PBR surface response.
Evaluated material values suitable for a wet-surface shader.