Commit 95944522 authored by Florian Oetke's avatar Florian Oetke
Browse files

frame animations for particles

parent dde6305c
......@@ -2,14 +2,14 @@
"keyframes": [
{
"time": 0,
"color": {"mean":{"hue":0}, "stddev":{"hue":0.5}},
"color": {"mean":{"hue":0, "saturation":1}, "stddev":{"hue":0.5}},
"size": {"mean": {"x": 0.05, "y":0.15, "z":0.04}, "stddev":{"x": 0.04, "y":0.02, "z":0.02}},
"rotation": {"mean":{"angle":0}, "stddev":{"elevation":1, "azimuth":1, "angle": 1}},
"drag": 0.1
},
{
"time": 4,
"color": {"mean":{"hue":0}, "stddev":{"hue":0}},
"color": {"mean":{"hue":0, "saturation":1}, "stddev":{"hue":1}},
"size": {"mean": {"x": 0.01, "y":0.1, "z":0.01}},
"rotation": {"mean":{"angle":1}, "stddev":{"elevation":1, "azimuth":1, "angle": 1}},
"drag": 1.0
......
{
"keyframes": [
{
"time": 0,
"color": {"mean":{"value":0.5}, "stddev":{"value":0.3}},
"time": 0.1,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0, "y":0, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 4,
"color": {"mean":{"value":0.5}, "stddev":{"value":0.3}},
"size": {"mean": {"x": 0.1}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":1}, "stddev":{"angle": 1}},
"time": 0.2,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.2, "y":0, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 0.3,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.4, "y":0, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 0.4,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.6, "y":0, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 0.5,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.8, "y":0, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 0.6,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0, "y":0.333, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 0.7,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.2, "y":0.333, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 0.8,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.4, "y":0.333, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 0.9,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.6, "y":0.333, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 1,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.8, "y":0.333, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 1.1,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0, "y":0.666, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 1.2,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.2, "y":0.666, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 1.3,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.4, "y":0.666, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 1.4,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.6, "y":0.666, "z":0.2, "w":0.333},
"drag": 0.5
},
{
"time": 1.5,
"color": {"mean":{"value":0.8}, "stddev":{"value":0.2}},
"size": {"mean": {"x": 0.08}, "stddev":{"x": 0.04}},
"rotation": {"mean":{"angle":0}, "stddev":{"angle": 1}},
"clip_rect": {"x":0.8, "y":0.666, "z":0.2, "w":0.333},
"drag": 0.5
}
],
"loop_keyframe_time": 1.5,
"symmetric_scaling": true,
"rotate_with_velocity": false,
"blend": "solid",
"geometry": "billboard",
"material_id": "mat:billboard_material.msf",
"material_id": "tex:smoke_particle.ktx",
"update_script_id": "comp_shader:particle_update_simple"
}
......@@ -176,6 +176,9 @@ namespace mirrage::asset {
template <typename T>
void remove_stateful_loader();
template <typename T>
auto load_stream(asset::istream) -> Ptr<T>;
private:
friend class ostream;
......
......@@ -221,6 +221,24 @@ namespace mirrage::asset {
_containers.erase(util::type_uid_of<T>());
}
template <typename T>
auto Asset_manager::load_stream(asset::istream stream) -> Ptr<T>
{
auto container = _find_container<T>();
if(container.is_nothing())
throw std::system_error(Asset_error::stateful_loader_not_initialized, util::type_name<T>());
auto new_value = container.get_or_throw().load(std::move(stream));
if constexpr(std::is_same_v<decltype(new_value), async::task<T>>)
return Ptr<T>(stream.aid(), new_value.share());
else if constexpr(std::is_same_v<decltype(new_value), async::shared_task<T>>)
return Ptr<T>(stream.aid(), std::move(new_value));
else
return Ptr<T>(stream.aid(), async::make_task(std::move(new_value)).share());
}
template <typename T>
auto Asset_manager::_find_container() -> util::maybe<detail::Asset_container<T>&>
{
......
......@@ -69,7 +69,6 @@ namespace mirrage::renderer {
};
using Material_ptr = asset::Ptr<Material>;
struct Model_vertex {
glm::vec3 position;
glm::vec3 normal;
......
......@@ -108,17 +108,18 @@ namespace mirrage::renderer {
negative_mass_scale);
struct Particle_keyframe {
Random_value<Particle_color> color = {{1, 1, 1, 1}};
Random_value<Particle_rotation> rotation = {};
Random_value<glm::vec4> size = {{1.f, 1.f, 1.f, 0.f}};
Random_value<Particle_color> color = {{1, 0, 1, 1}};
Random_value<Particle_rotation> rotation = {};
Random_value<glm::vec4> size = {{1.f, 1.f, 1.f, 0.f}};
glm::vec4 clip_rect = {0, 0, 1, 1};
float time = 0;
float base_mass = 1;
float density = 0;
float drag = 0.f;
};
sf2_structDef(Particle_keyframe, color, rotation, size, time, base_mass, density, drag);
static_assert(sizeof(Particle_keyframe) == sizeof(float) * (4 * 3 * 2 + 4),
sf2_structDef(Particle_keyframe, color, rotation, size, clip_rect, time, base_mass, density, drag);
static_assert(sizeof(Particle_keyframe) == sizeof(float) * (4 * 3 * 2 + 4 + 4),
"Particle_keyframe contains padding");
/// describes how living particles are updated and drawn
......@@ -136,8 +137,9 @@ namespace mirrage::renderer {
bool size_normal_distribution_y = false;
bool size_normal_distribution_z = false;
bool rotate_with_velocity = false;
bool symmetric_scaling = false; //< also use x size for y and z
bool rotate_with_velocity = false;
bool symmetric_scaling = false; //< also use x size for y and z
float loop_keyframe_time = 0.f;
Particle_blend_mode blend = Particle_blend_mode::transparent;
Particle_geometry geometry = Particle_geometry::billboard;
......@@ -169,6 +171,7 @@ namespace mirrage::renderer {
size_normal_distribution_z,
rotate_with_velocity,
symmetric_scaling,
loop_keyframe_time,
blend,
geometry,
update_range,
......
......@@ -18,9 +18,7 @@ layout(location = 5) in uvec4 particle_data;
layout(location = 0) out vec3 out_view_pos;
layout(location = 1) out vec3 out_normal;
layout(location = 2) out vec2 out_tex_coords;
layout(location = 3) out vec4 out_particle_velocity;
layout(location = 4) out uvec4 out_particle_data;
layout(location = 5) out vec4 out_particle_color;
layout(location = 3) out vec4 out_particle_color;
layout(std140, set=2, binding = 0) readonly buffer Particle_type_config {
PARTICLE_TYPE_CONFIG
......@@ -102,7 +100,7 @@ void main() {
float keyframe_t = uintBitsToFloat(particle_data.w);
vec3 size = max(vec3(0,0,0), calc_size(keyframe_a, keyframe_b, keyframe_t, rand_size));
if(particle_config.symmetric_scaling!=0)
if((particle_config.flags&4)!=0)
size.y = size.z = size.x;
vec4 p = vec4(position * size, 1.0);
......@@ -112,7 +110,9 @@ void main() {
p.xyz = quaternion_rotate(p.xyz, rotation);
n.xyz = quaternion_rotate(n.xyz, rotation);
if(particle_config.rotate_with_velocity==2) {
uint rotate_with_velocity = particle_config.flags & 3;
if(rotate_with_velocity==2) {
vec4 view_vel = (global_uniforms.view_mat * vec4(particle_velocity.xyz, 0.0));
float len_2d = length(view_vel.xy);
......@@ -128,7 +128,7 @@ void main() {
n.xy = vec2(n.x*ca - n.y*sa, n.x*sa + n.y*ca);
}
} else if(particle_config.rotate_with_velocity==1) {
} else if(rotate_with_velocity==1) {
vec3 dir = particle_velocity.xyz;
float dir_len = length(dir);
if(dir_len > 0) {
......@@ -155,8 +155,10 @@ void main() {
out_view_pos = view_pos.xyz / view_pos.w;
out_normal = (global_uniforms.view_mat * n).xyz;
out_tex_coords = tex_coords;
out_particle_velocity = particle_velocity;
out_particle_data = particle_data;
vec4 clip_rect = particle_config.keyframes[keyframe_t<0.5 ? keyframe_a : keyframe_b].clip_rect;
out_tex_coords.y = 1-out_tex_coords.y;
out_tex_coords = clip_rect.xy + out_tex_coords * clip_rect.zw;
out_tex_coords.y = 1-out_tex_coords.y;
vec4 color = calc_color(keyframe_a, keyframe_b, keyframe_t, rand_color);;
out_particle_color = vec4(hsv2rgb(color.xyz), color.a);
......
......@@ -108,6 +108,8 @@ struct Particle_keyframe {
Random_vec4 rotation; // elevation, azimuth, angle
Random_vec4 size; // xyz
vec4 clip_rect;
float time;
float base_mass;
float density;
......@@ -127,11 +129,15 @@ struct Particle_keyframe {
1 << 7 = 128 : size[0] normal/uniform
1 << 8 = 256 : size[1] normal/uniform
1 << 9 = 512 : size[2] normal/uniform
flags:
0b011: rotate_with_velocity
0b100: symmetric_scaling
*/
#define PARTICLE_TYPE_CONFIG \
uint normal_distribution_flags;\
uint rotate_with_velocity; \
uint symmetric_scaling; \
uint flags; \
float loop_keyframe_time; \
uint keyframe_count; \
Particle_keyframe[] keyframes;
......@@ -74,8 +74,14 @@ void main() {
uint out_index = out_offset + feedback.ranges[feedback_index].offset;
// update keyframe
// TODO: particle_config.loop_keyframe_time
float age = ttl[1] - ttl[0];
uint keyframe = pin.particles[index].data.z;
if(particle_config.loop_keyframe_time>0) {
keyframe = 0;
age = mod(age, particle_config.loop_keyframe_time);
}
for(uint i=keyframe+1; i<particle_config.keyframe_count-1; i++) {
if(particle_config.keyframes[i].time > age) {
keyframe = i - 1;
......@@ -113,6 +119,8 @@ void main() {
: uniform_size.x*2-1;
vec3 size = calc_size(keyframe, keyframe_b, keyframe_t, size_rand);
if((particle_config.flags&4)!=0)
size.y = size.z = size.x;
float volumn = size.x * size.y * size.z;
float mass = mix(particle_config.keyframes[keyframe].base_mass,
......
......@@ -11,9 +11,7 @@ layout(early_fragment_tests) in;
layout(location = 0) in vec3 view_pos;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 tex_coords;
layout(location = 3) in vec4 out_particle_velocity;
layout(location = 4) in flat uvec4 out_particle_data;
layout(location = 5) in vec4 out_particle_color;
layout(location = 3) in vec4 out_particle_color;
layout(location = 0) out vec4 depth_out;
......
......@@ -133,16 +133,46 @@ namespace mirrage::asset {
auto Loader<renderer::Material>::load(istream in) -> async::task<renderer::Material>
{
auto data = Loader<renderer::Material_data>::load(std::move(in));
auto load_tex = [&](auto&& id, asset::AID placeholder) {
return _assets.load<graphic::Texture_2D>(id.empty() ? placeholder : asset::AID("tex"_strid, id));
};
auto sub_id = data.substance_id;
auto desc_set =
_descriptor_set_pool.create_descriptor(_descriptor_set_layout, renderer::material_textures);
if(in.aid().type() == "tex"_strid) {
// single texture material
auto albedo = _assets.load_stream<graphic::Texture_2D>(std::move(in));
auto normal = _assets.load<graphic::Texture_2D>("tex:default_normal"_aid);
auto brdf = _assets.load<graphic::Texture_2D>("tex:default_brdf"_aid);
auto emission = _assets.load<graphic::Texture_2D>("tex:placeholder"_aid);
auto all_loaded = async::when_all(albedo.internal_task(),
normal.internal_task(),
brdf.internal_task(),
emission.internal_task());
using Task_type = decltype(all_loaded)::result_type;
return all_loaded.then([=, desc_set = std::move(desc_set)](const Task_type&) mutable {
return renderer::Material(_device,
std::move(desc_set),
_sampler,
albedo,
normal,
brdf,
emission,
true,
false,
false,
false,
"default"_strid);
});
}
auto data = Loader<renderer::Material_data>::load(std::move(in));
auto sub_id = data.substance_id;
auto albedo = load_tex(data.albedo_aid, "tex:placeholder"_aid);
auto normal = load_tex(data.normal_aid, "tex:default_normal"_aid);
auto brdf = load_tex(data.brdf_aid, "tex:default_brdf"_aid);
......
......@@ -58,8 +58,8 @@ namespace mirrage::renderer {
struct Type_uniforms {
std::uint32_t normal_distribution_flags;
std::uint32_t rotate_with_velocity;
std::uint32_t symmetric_scaling;
std::uint32_t flags; // 0b1: rotate_with_velocity; 0b10: symmetric_scaling
float loop_keyframe_time;
std::uint32_t keyframe_count;
// + keyframes
};
......@@ -503,9 +503,10 @@ namespace mirrage::renderer {
auto keyframes = reinterpret_cast<char*>(uniforms_ptr + sizeof(Type_uniforms));
uniforms.keyframe_count = gsl::narrow<std::uint32_t>(cfg.keyframes.size());
uniforms.rotate_with_velocity =
cfg.rotate_with_velocity ? (cfg.geometry == Particle_geometry::billboard ? 2 : 1) : 0;
uniforms.symmetric_scaling = cfg.symmetric_scaling ? 1 : 0;
auto rotate_with_velocity =
cfg.rotate_with_velocity ? (cfg.geometry == Particle_geometry::billboard ? 2u : 1u) : 0u;
uniforms.flags = (cfg.symmetric_scaling ? 1u : 0u) << 2 | rotate_with_velocity;
uniforms.loop_keyframe_time = cfg.loop_keyframe_time;
auto ndf = std::uint32_t(0);
auto i = std::uint32_t(0);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment