Commit 9095899b authored by Florian Oetke's avatar Florian Oetke
Browse files

transparent particles

parent b1013c2b
......@@ -10,7 +10,8 @@
"shadow_size": 24,
"near_plane": 1.0,
"far_plane": 80,
"update_frequency": 1
"update_frequency": 1,
"light_particles": true
},
"Shadowcaster": {
},
......
......@@ -8,7 +8,7 @@
"size": {"x":0, "y":0},
"direction": {"mean":{"elevation":-1, "azimuth":0}, "stddev":{"elevation":0.4, "azimuth":0.4}},
"ttl": {"mean": 20, "stddev": 4},
"ttl": {"mean": 30, "stddev": 0},
"velocity": {"mean": 0.01, "stddev": 0.008},
......
......@@ -25,12 +25,17 @@ namespace mirrage::graphic {
auto update(std::int32_t dest_offset, gsl::span<const char> data) -> bool;
template <class T>
auto update_objs(std::int32_t dest_offset, gsl::span<T> obj) -> bool
auto update_objs(std::int32_t dest_offset, gsl::span<const T> obj) -> bool
{
static_assert(std::is_standard_layout<T>::value, "");
return update(dest_offset,
gsl::span<const char>(reinterpret_cast<const char*>(obj.data()), obj.size_bytes()));
}
template <class T>
auto update_objs(std::int32_t dest_offset, const std::initializer_list<T>& obj) -> bool
{
return update_objs(dest_offset, gsl::span<const T>(obj));
}
template <class T, class F>
auto update_objects(std::int32_t dest_offset, F&& f) -> bool
......
......@@ -41,6 +41,8 @@ frag_shader:model_alphatest = shader/model_alphatest.frag.spv
vert_shader:particle = shader/particle.vert.spv
frag_shader:particle_solid = shader/particle_solid.frag.spv
vert_shader:particle_transparent = shader/particle_transparent.vert.spv
vert_shader:particle_transparent_lit = shader/particle_transparent_lit.vert.spv
frag_shader:particle_transparent_lit = shader/particle_transparent_lit.frag.spv
frag_shader:particle_transparent_unlit = shader/particle_transparent_unlit.frag.spv
......
......@@ -52,7 +52,8 @@ namespace mirrage::renderer {
float max_display_luminance = 150.0f;
float amient_light_intensity = 0.1f;
int transparent_particle_mip_level = 1;
int transparent_particle_mip_level = 1;
bool particle_fragment_shadows = true;
bool taa = true;
bool ssao = true;
......@@ -82,6 +83,7 @@ namespace mirrage::renderer {
max_display_luminance,
amient_light_intensity,
transparent_particle_mip_level,
particle_fragment_shadows,
taa,
ssao,
bloom,
......
......@@ -36,6 +36,9 @@ namespace mirrage::renderer {
auto shadow_color() const noexcept { return _shadow_color; }
auto shadowmap_id() const noexcept { return _shadowmap_id; }
void light_particles(bool b) noexcept { _light_particles = b; }
auto light_particles() const noexcept { return _light_particles; }
auto calc_shadowmap_view_proj(ecs::components::Transform_comp& transform) const -> glm::mat4;
auto needs_update() { return _shadow_last_update >= _shadow_update_frequency; }
......@@ -54,6 +57,7 @@ namespace mirrage::renderer {
util::Distance _source_radius;
float _intensity; // in lux
util::Rgb _color;
bool _light_particles = false;
float _shadow_intensity = 0; // in lux
util::Rgb _shadow_color = {0, 0, 0};
bool _shadowcaster = true;
......
......@@ -47,7 +47,7 @@ namespace mirrage::renderer {
bool has_emission,
util::Str_id substance_id);
void bind(graphic::Render_pass& pass) const;
void bind(graphic::Render_pass& pass, int bind_point = 1) const;
auto substance_id() const noexcept { return _substance_id; }
auto has_albedo() const noexcept { return _has_albedo; }
......
......@@ -36,8 +36,8 @@ namespace mirrage::renderer {
vk::UniquePipeline _pipeline;
};
enum class Particle_blend_mode { solid, transparent };
sf2_enumDef(Particle_blend_mode, solid, transparent);
enum class Particle_blend_mode { solid, transparent, transparent_unlit };
sf2_enumDef(Particle_blend_mode, solid, transparent, transparent_unlit);
enum class Particle_geometry { billboard, mesh };
sf2_enumDef(Particle_geometry, billboard, mesh);
......
......@@ -3,6 +3,7 @@
#include <mirrage/renderer/deferred_renderer.hpp>
#include <mirrage/graphic/render_pass.hpp>
#include <mirrage/graphic/streamed_buffer.hpp>
namespace mirrage::renderer {
......@@ -13,7 +14,7 @@ namespace mirrage::renderer {
public:
using Factory = Transparent_pass_factory;
Transparent_pass(Deferred_renderer&, graphic::Render_target_2D& target);
Transparent_pass(Deferred_renderer&, ecs::Entity_manager& ecs, graphic::Render_target_2D& target);
void update(util::Time dt) override;
void draw(Frame_data&) override;
......@@ -22,20 +23,24 @@ namespace mirrage::renderer {
private:
Deferred_renderer& _renderer;
ecs::Entity_manager& _ecs;
vk::Format _revealage_format;
graphic::Render_target_2D _accum;
graphic::Render_target_2D _revealage;
vk::UniqueSampler _sampler;
graphic::Image_descriptor_set_layout _desc_set_layout;
graphic::DescriptorSet _accum_descriptor_set;
std::vector<graphic::DescriptorSet> _compose_descriptor_sets;
vk::UniqueSampler _sampler;
vk::UniqueDescriptorSetLayout _desc_set_layout;
graphic::DescriptorSet _accum_descriptor_set;
std::vector<graphic::DescriptorSet> _compose_descriptor_sets;
std::vector<graphic::Framebuffer> _accum_framebuffers;
graphic::Render_pass _accum_render_pass;
graphic::Framebuffer _compose_framebuffer;
graphic::Render_pass _compose_render_pass;
graphic::Dynamic_buffer _light_uniforms;
std::vector<char> _light_uniforms_tmp;
};
class Transparent_pass_factory : public Render_pass_factory {
......
......@@ -114,6 +114,7 @@ namespace mirrage::renderer {
};
struct Particle_draw {
ecs::Entity_handle entity;
Particle_emitter* emitter;
Particle_system* system;
const Particle_type_config* type_cfg;
......@@ -121,11 +122,13 @@ namespace mirrage::renderer {
std::uint32_t culling_mask;
Particle_draw() = default;
Particle_draw(Particle_emitter& emitter,
Particle_draw(ecs::Entity_handle entity,
Particle_emitter& emitter,
Particle_system& system,
gsl::span<Particle_effector_config> effectors,
std::uint32_t culling_mask)
: emitter(&emitter)
: entity(entity)
, emitter(&emitter)
, system(&system)
, type_cfg(&*emitter.cfg().type)
, effectors(effectors)
......
......@@ -72,7 +72,7 @@ void main() {
if(shadow>0.0) {
vec3 diffuse;
out_color = vec4(brdf(albedo, F0, roughness, N, V, L, radiance, diffuse) * shadow, 1.0);
out_color = vec4(brdf_without_NdotL(albedo, F0, roughness, N, V, L, radiance, diffuse) * shadow, 1.0);
out_color_diff = vec4(diffuse * shadow, 1.0);
}
......
......@@ -2,10 +2,7 @@
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#include "global_uniforms.glsl"
#include "particle/data_structures.glsl"
#include "color_conversion.glsl"
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
......@@ -15,7 +12,7 @@ layout(location = 3) in vec4 particle_position;
layout(location = 4) in vec4 particle_velocity;
layout(location = 5) in uvec4 particle_data;
layout(location = 0) out vec3 out_view_pos;
layout(location = 0) out vec4 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_color;
......@@ -35,136 +32,8 @@ out gl_PerVertex {
vec4 gl_Position;
};
vec3 calc_size(uint keyframe_a, uint keyframe_b, float t, vec3 rand) {
return mix(rand_xyz(particle_config.keyframes[keyframe_a].size, rand),
rand_xyz(particle_config.keyframes[keyframe_b].size, rand),
t);
}
vec4 calc_rotation(uint keyframe_a, uint keyframe_b, float t, vec3 rand) {
return normalize(mix(rand_quat(particle_config.keyframes[keyframe_a].rotation, rand),
rand_quat(particle_config.keyframes[keyframe_b].rotation, rand),
t));
}
vec4 calc_color(uint keyframe_a, uint keyframe_b, float t, vec4 rand) {
return mix(rand_vec4(particle_config.keyframes[keyframe_a].color, rand),
rand_vec4(particle_config.keyframes[keyframe_b].color, rand),
t);
}
void calc_random(uint seed, out vec3 rotation, out vec3 size, out vec4 color) {
vec2 uniform_rotation = uniform_rand(seed, 20, 21);
vec2 uniform_shared = uniform_rand(seed, 22, 23);
vec2 uniform_size = uniform_rand(seed, 24, 25);
vec4 uniform_color = vec4(uniform_rand(seed, 10, 11), uniform_rand(seed, 12, 13));
vec2 normal_rotation = uniform_to_normal_rand(uniform_rotation);
vec2 normal_shared = uniform_to_normal_rand(uniform_shared);
vec2 normal_size = uniform_to_normal_rand(uniform_size);
vec4 normal_color = vec4(uniform_to_normal_rand(uniform_color.xy), uniform_to_normal_rand(uniform_color.zw));
color.x = (particle_config.normal_distribution_flags & 1)!=0 ? normal_color.x
: uniform_color.x*2-1;
color.y = (particle_config.normal_distribution_flags & 2)!=0 ? normal_color.y
: uniform_color.y*2-1;
color.z = (particle_config.normal_distribution_flags & 4)!=0 ? normal_color.z
: uniform_color.z*2-1;
color.w = (particle_config.normal_distribution_flags & 8)!=0 ? normal_color.w
: uniform_color.w*2-1;
size.x = (particle_config.normal_distribution_flags & 16)!=0 ? normal_shared.y
: uniform_shared.y*2-1;
size.y = (particle_config.normal_distribution_flags & 32)!=0 ? normal_size.x
: uniform_size.x*2-1;
size.z = (particle_config.normal_distribution_flags & 64)!=0 ? normal_size.x
: uniform_size.x*2-1;
rotation.x = (particle_config.normal_distribution_flags & 128)!=0 ? normal_rotation.x
: uniform_rotation.x*2-1;
rotation.y = (particle_config.normal_distribution_flags & 256)!=0 ? normal_rotation.y
: uniform_rotation.y*2-1;
rotation.z = (particle_config.normal_distribution_flags & 512)!=0 ? normal_shared.x
: uniform_shared.x*2-1;
}
#include "particle.vert_base.glsl"
void main() {
uint seed = particle_data.y;
vec3 rand_rotation;
vec3 rand_size;
vec4 rand_color;
calc_random(seed, rand_rotation, rand_size, rand_color);
uint keyframe_a = particle_data.z;
uint keyframe_b = min(keyframe_a+1, particle_config.keyframe_count-1);
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.flags&4)!=0)
size.y = size.z = size.x;
vec4 p = vec4(position * size, 1.0);
vec4 n = vec4(normal, 0.0);
vec4 rotation = calc_rotation(keyframe_a, keyframe_b, keyframe_t, rand_rotation);
p.xyz = quaternion_rotate(p.xyz, rotation);
n.xyz = quaternion_rotate(n.xyz, rotation);
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);
if(len_2d >= 0.001) {
view_vel.xy = view_vel.xy / len_2d;
float angle = (view_vel.y<0? -1.0 : 1.0) * acos(view_vel.x);
angle -= 3.1415926*0.5;
float sa = sin(angle);
float ca = cos(angle);
p.xy = vec2(p.x*ca - p.y*sa, p.x*sa + p.y*ca);
n.xy = vec2(n.x*ca - n.y*sa, n.x*sa + n.y*ca);
}
} else if(rotate_with_velocity==1) {
vec3 dir = particle_velocity.xyz;
float dir_len = length(dir);
if(dir_len > 0) {
dir /= dir_len;
if(dir.y <= -1.0) {
p.xyz = vec3(-p.x, -p.y, p.z);
n.xyz = vec3(-n.x, -n.y, n.z);
} else if(dir.y < 1.0) {
vec3 my = normalize(dir);
vec3 mz = normalize(cross(my, vec3(0,1,0)));
vec3 mx = normalize(cross(my, mz));
p.xyz = mat3(mx,my,mz) * p.xyz;
n.xyz = mat3(mx,my,mz) * n.xyz;
}
}
}
p = model_uniforms.model_to_view * p;
n = model_uniforms.model_to_view * n;
vec4 view_pos = global_uniforms.view_mat * vec4(p.xyz + particle_position.xyz, 1.0);
out_view_pos = view_pos.xyz / view_pos.w;
out_normal = (global_uniforms.view_mat * n).xyz;
out_tex_coords = tex_coords;
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);
vec4 screen_pos = global_uniforms.proj_mat * view_pos;
out_screen_pos = screen_pos;
gl_Position = screen_pos;
base_main();
}
#include "global_uniforms.glsl"
#include "color_conversion.glsl"
vec3 calc_size(uint keyframe_a, uint keyframe_b, float t, vec3 rand) {
return mix(rand_xyz(particle_config.keyframes[keyframe_a].size, rand),
rand_xyz(particle_config.keyframes[keyframe_b].size, rand),
t);
}
vec4 calc_rotation(uint keyframe_a, uint keyframe_b, float t, vec3 rand) {
return normalize(mix(rand_quat(particle_config.keyframes[keyframe_a].rotation, rand),
rand_quat(particle_config.keyframes[keyframe_b].rotation, rand),
t));
}
vec4 calc_color(uint keyframe_a, uint keyframe_b, float t, vec4 rand) {
return mix(rand_vec4(particle_config.keyframes[keyframe_a].color, rand),
rand_vec4(particle_config.keyframes[keyframe_b].color, rand),
t);
}
void calc_random(uint seed, out vec3 rotation, out vec3 size, out vec4 color) {
vec2 uniform_rotation = uniform_rand(seed, 20, 21);
vec2 uniform_shared = uniform_rand(seed, 22, 23);
vec2 uniform_size = uniform_rand(seed, 24, 25);
vec4 uniform_color = vec4(uniform_rand(seed, 10, 11), uniform_rand(seed, 12, 13));
vec2 normal_rotation = uniform_to_normal_rand(uniform_rotation);
vec2 normal_shared = uniform_to_normal_rand(uniform_shared);
vec2 normal_size = uniform_to_normal_rand(uniform_size);
vec4 normal_color = vec4(uniform_to_normal_rand(uniform_color.xy), uniform_to_normal_rand(uniform_color.zw));
color.x = (particle_config.normal_distribution_flags & 1)!=0 ? normal_color.x
: uniform_color.x*2-1;
color.y = (particle_config.normal_distribution_flags & 2)!=0 ? normal_color.y
: uniform_color.y*2-1;
color.z = (particle_config.normal_distribution_flags & 4)!=0 ? normal_color.z
: uniform_color.z*2-1;
color.w = (particle_config.normal_distribution_flags & 8)!=0 ? normal_color.w
: uniform_color.w*2-1;
size.x = (particle_config.normal_distribution_flags & 16)!=0 ? normal_shared.y
: uniform_shared.y*2-1;
size.y = (particle_config.normal_distribution_flags & 32)!=0 ? normal_size.x
: uniform_size.x*2-1;
size.z = (particle_config.normal_distribution_flags & 64)!=0 ? normal_size.x
: uniform_size.x*2-1;
rotation.x = (particle_config.normal_distribution_flags & 128)!=0 ? normal_rotation.x
: uniform_rotation.x*2-1;
rotation.y = (particle_config.normal_distribution_flags & 256)!=0 ? normal_rotation.y
: uniform_rotation.y*2-1;
rotation.z = (particle_config.normal_distribution_flags & 512)!=0 ? normal_shared.x
: uniform_shared.x*2-1;
}
void base_main() {
uint seed = particle_data.y;
vec3 rand_rotation;
vec3 rand_size;
vec4 rand_color;
calc_random(seed, rand_rotation, rand_size, rand_color);
uint keyframe_a = particle_data.z;
uint keyframe_b = min(keyframe_a+1, particle_config.keyframe_count-1);
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.flags&4)!=0)
size.y = size.z = size.x;
vec4 p = vec4(position * size, 1.0);
vec4 n = vec4(normal, 0.0);
vec4 rotation = calc_rotation(keyframe_a, keyframe_b, keyframe_t, rand_rotation);
p.xyz = quaternion_rotate(p.xyz, rotation);
n.xyz = quaternion_rotate(n.xyz, rotation);
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);
if(len_2d >= 0.001) {
view_vel.xy = view_vel.xy / len_2d;
float angle = (view_vel.y<0? -1.0 : 1.0) * acos(view_vel.x);
angle -= 3.1415926*0.5;
float sa = sin(angle);
float ca = cos(angle);
p.xy = vec2(p.x*ca - p.y*sa, p.x*sa + p.y*ca);
n.xy = vec2(n.x*ca - n.y*sa, n.x*sa + n.y*ca);
}
} else if(rotate_with_velocity==1) {
vec3 dir = particle_velocity.xyz;
float dir_len = length(dir);
if(dir_len > 0) {
dir /= dir_len;
if(dir.y <= -1.0) {
p.xyz = vec3(-p.x, -p.y, p.z);
n.xyz = vec3(-n.x, -n.y, n.z);
} else if(dir.y < 1.0) {
vec3 my = normalize(dir);
vec3 mz = normalize(cross(my, vec3(0,1,0)));
vec3 mx = normalize(cross(my, mz));
p.xyz = mat3(mx,my,mz) * p.xyz;
n.xyz = mat3(mx,my,mz) * n.xyz;
}
}
}
p = model_uniforms.model_to_view * p;
n = model_uniforms.model_to_view * n;
vec4 view_pos = global_uniforms.view_mat * vec4(p.xyz + particle_position.xyz, 1.0);
out_view_pos = view_pos;
out_normal = (global_uniforms.view_mat * n).xyz;
out_tex_coords = tex_coords;
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);
vec4 screen_pos = global_uniforms.proj_mat * view_pos;
out_screen_pos = screen_pos;
gl_Position = screen_pos;
}
......@@ -74,7 +74,6 @@ 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) {
......
......@@ -8,10 +8,11 @@
layout(early_fragment_tests) in;
layout(location = 0) in vec3 view_pos;
layout(location = 0) in vec4 view_pos;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 tex_coords;
layout(location = 3) in vec4 out_particle_color;
layout(location = 4) in vec4 out_screen_pos;
layout(location = 0) out vec4 depth_out;
......@@ -52,7 +53,7 @@ void main() {
float metallic = brdf.g;
roughness = mix(0.01, 0.99, roughness*roughness);
depth_out = vec4(-view_pos.z / global_uniforms.proj_planes.y, 0,0,1);
depth_out = vec4(-view_pos.z/view_pos.w / global_uniforms.proj_planes.y, 0,0,1);
albedo_mat_id_out = vec4(albedo.rgb, 0.0);
mat_data_out = vec4(encode_normal(N), roughness, metallic);
......@@ -74,9 +75,11 @@ vec3 decode_tangent_normal(vec2 tn) {
vec3 tangent_space_to_world(vec3 N) {
vec3 VN = normalize(normal);
vec3 vp = view_pos.xyz / view_pos.w;
// calculate tangent
vec3 p_dx = dFdx(view_pos);
vec3 p_dy = dFdy(view_pos);
vec3 p_dx = dFdx(vp);
vec3 p_dy = dFdy(vp);
vec2 tc_dx = dFdx(tex_coords);
vec2 tc_dy = dFdy(tex_coords);
......
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#include "particle/data_structures.glsl"
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 tex_coords;
layout(location = 3) in vec4 particle_position;
layout(location = 4) in vec4 particle_velocity;
layout(location = 5) in uvec4 particle_data;
layout(location = 0) out vec4 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_color;
layout(location = 4) out vec4 out_screen_pos;
layout(std140, set=4, binding = 0) readonly buffer Particle_type_config {
PARTICLE_TYPE_CONFIG
} particle_config;
layout(push_constant) uniform Per_model_uniforms {
mat4 model_to_view;
vec4 light_color;
vec4 options;
} model_uniforms;
out gl_PerVertex {
vec4 gl_Position;
};
#include "particle.vert_base.glsl"
void main() {
base_main();
}