mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Mostly snaked through another rendering pipeline
This commit is contained in:
parent
b8bb77a62c
commit
0794f980fe
104
assets/voxygen/shaders/trail-frag.glsl
Normal file
104
assets/voxygen/shaders/trail-frag.glsl
Normal file
@ -0,0 +1,104 @@
|
||||
#version 420 core
|
||||
|
||||
#include <constants.glsl>
|
||||
|
||||
#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION
|
||||
|
||||
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY
|
||||
|
||||
#if (FLUID_MODE == FLUID_MODE_CHEAP)
|
||||
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
|
||||
#elif (FLUID_MODE == FLUID_MODE_SHINY)
|
||||
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE
|
||||
#endif
|
||||
|
||||
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
|
||||
|
||||
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
|
||||
|
||||
#define HAS_SHADOW_MAPS
|
||||
|
||||
#include <globals.glsl>
|
||||
|
||||
layout(location = 0) in vec3 f_pos;
|
||||
layout(location = 1) flat in vec3 f_norm;
|
||||
layout(location = 2) in vec4 f_col;
|
||||
layout(location = 3) in float f_reflect;
|
||||
|
||||
layout(location = 0) out vec4 tgt_color;
|
||||
|
||||
#include <sky.glsl>
|
||||
#include <light.glsl>
|
||||
#include <lod.glsl>
|
||||
|
||||
const float FADE_DIST = 32.0;
|
||||
|
||||
void main() {
|
||||
vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz);
|
||||
vec3 view_dir = -cam_to_frag;
|
||||
|
||||
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY)
|
||||
float f_alt = alt_at(f_pos.xy);
|
||||
#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP)
|
||||
float f_alt = f_pos.z;
|
||||
#endif
|
||||
|
||||
#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP)
|
||||
vec4 f_shadow = textureBicubic(t_horizon, s_horizon, pos_to_tex(f_pos.xy));
|
||||
float sun_shade_frac = horizon_at2(f_shadow, f_alt, f_pos, sun_dir);
|
||||
#elif (SHADOW_MODE == SHADOW_MODE_NONE)
|
||||
float sun_shade_frac = 1.0;
|
||||
#endif
|
||||
float moon_shade_frac = 1.0;
|
||||
|
||||
float point_shadow = shadow_at(f_pos, f_norm);
|
||||
DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, f_pos);
|
||||
DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac);
|
||||
|
||||
vec3 surf_color = f_col.rgb;
|
||||
float alpha = 1.0;
|
||||
const float n2 = 1.5;
|
||||
const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2);
|
||||
const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2);
|
||||
const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2);
|
||||
const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2);
|
||||
float R_s = (f_pos.z < f_alt) ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x);
|
||||
|
||||
vec3 k_a = vec3(1.0) * f_reflect;
|
||||
vec3 k_d = vec3(1.0) * f_reflect;
|
||||
vec3 k_s = vec3(R_s) * f_reflect;
|
||||
|
||||
vec3 emitted_light, reflected_light;
|
||||
|
||||
// This is a bit of a hack. Because we can't find the volumetric lighting of each particle (they don't talk to the
|
||||
// CPU) we need to some how find an approximation of how much the sun is blocked. We do this by fading out the sun
|
||||
// as the particle moves underground. This isn't perfect, but it does at least mean that particles don't look like
|
||||
// they're exposed to the sun when in dungeons
|
||||
const float SUN_FADEOUT_DIST = 20.0;
|
||||
sun_info.block *= clamp((f_pos.z - f_alt) / SUN_FADEOUT_DIST + 1, 0, 1);
|
||||
|
||||
// To account for prior saturation.
|
||||
float max_light = 0.0;
|
||||
|
||||
vec3 cam_attenuation = vec3(1);
|
||||
float fluid_alt = max(f_pos.z + 1, floor(f_alt + 1));
|
||||
vec3 mu = medium.x == MEDIUM_WATER ? MU_WATER : vec3(0.0);
|
||||
#if (FLUID_MODE == FLUID_MODE_SHINY)
|
||||
cam_attenuation =
|
||||
medium.x == MEDIUM_WATER ? compute_attenuation_point(cam_pos.xyz, view_dir, MU_WATER, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/f_pos)
|
||||
: compute_attenuation_point(f_pos, -view_dir, vec3(0), fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz);
|
||||
#endif
|
||||
|
||||
max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, view_dir, f_pos, MU_WATER, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
|
||||
|
||||
max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
|
||||
|
||||
// Allow particles to glow at night
|
||||
// TODO: Not this
|
||||
emitted_light += max(f_col.rgb - 1.0, vec3(0));
|
||||
|
||||
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light * f_reflect);
|
||||
|
||||
// Temporarily disable particle transparency to avoid artifacts
|
||||
tgt_color = vec4(surf_color, 1.0 /*f_col.a*/);
|
||||
}
|
650
assets/voxygen/shaders/trail-vert.glsl
Normal file
650
assets/voxygen/shaders/trail-vert.glsl
Normal file
@ -0,0 +1,650 @@
|
||||
#version 420 core
|
||||
|
||||
#include <globals.glsl>
|
||||
|
||||
layout (locati#version 420 core
|
||||
|
||||
#include <constants.glsl>
|
||||
|
||||
#define LIGHTING_TYPE LIGHTING_TYPE_REFLECTION
|
||||
|
||||
#define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY
|
||||
|
||||
#define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE
|
||||
|
||||
#define LIGHTING_DISTRIBUTION_SCHEME LIGHTING_DISTRIBUTION_SCHEME_MICROFACET
|
||||
|
||||
#define LIGHTING_DISTRIBUTION LIGHTING_DISTRIBUTION_BECKMANN
|
||||
|
||||
#include <globals.glsl>
|
||||
#include <srgb.glsl>
|
||||
#include <random.glsl>
|
||||
#include <lod.glsl>
|
||||
|
||||
layout(location = 0) in vec3 v_pos;
|
||||
// in uint v_col;
|
||||
layout(location = 1) in uint v_norm_ao;
|
||||
layout(location = 2) in float inst_time;
|
||||
layout(location = 3) in float inst_lifespan;
|
||||
layout(location = 4) in float inst_entropy;
|
||||
layout(location = 5) in int inst_mode;
|
||||
layout(location = 6) in vec3 inst_dir;
|
||||
layout(location = 7) in vec3 inst_pos;
|
||||
|
||||
layout(location = 0) out vec3 f_pos;
|
||||
layout(location = 1) flat out vec3 f_norm;
|
||||
layout(location = 2) out vec4 f_col;
|
||||
//layout(location = x) out float f_ao;
|
||||
//layout(location = x) out float f_light;
|
||||
layout(location = 3) out float f_reflect;
|
||||
|
||||
const float SCALE = 1.0 / 11.0;
|
||||
|
||||
// Modes
|
||||
const int SMOKE = 0;
|
||||
const int FIRE = 1;
|
||||
const int GUN_POWDER_SPARK = 2;
|
||||
const int SHRAPNEL = 3;
|
||||
|
||||
const int FIREWORK_BLUE = 4;
|
||||
const int FIREWORK_GREEN = 5;
|
||||
const int FIREWORK_PURPLE = 6;
|
||||
const int FIREWORK_RED = 7;
|
||||
const int FIREWORK_WHITE = 8;
|
||||
const int FIREWORK_YELLOW = 9;
|
||||
const int LEAF = 10;
|
||||
const int FIREFLY = 11;
|
||||
const int BEE = 12;
|
||||
const int GROUND_SHOCKWAVE = 13;
|
||||
const int ENERGY_HEALING = 14;
|
||||
const int ENERGY_NATURE = 15;
|
||||
const int FLAMETHROWER = 16;
|
||||
const int FIRE_SHOCKWAVE = 17;
|
||||
const int FIRE_BOWL = 18;
|
||||
const int SNOW = 19;
|
||||
const int EXPLOSION = 20;
|
||||
const int ICE = 21;
|
||||
const int LIFESTEAL_BEAM = 22;
|
||||
const int CULTIST_FLAME = 23;
|
||||
const int STATIC_SMOKE = 24;
|
||||
const int BLOOD = 25;
|
||||
const int ENRAGED = 26;
|
||||
const int BIG_SHRAPNEL = 27;
|
||||
const int LASER = 28;
|
||||
const int BUBBLES = 29;
|
||||
const int WATER = 30;
|
||||
const int ICE_SPIKES = 31;
|
||||
const int DRIP = 32;
|
||||
const int TORNADO = 33;
|
||||
const int DEATH = 34;
|
||||
|
||||
// meters per second squared (acceleration)
|
||||
const float earth_gravity = 9.807;
|
||||
|
||||
struct Attr {
|
||||
vec3 offs;
|
||||
vec3 scale;
|
||||
vec4 col;
|
||||
mat4 rot;
|
||||
};
|
||||
|
||||
float lifetime = tick.x - inst_time;
|
||||
|
||||
vec3 linear_motion(vec3 init_offs, vec3 vel) {
|
||||
return init_offs + vel * lifetime;
|
||||
}
|
||||
|
||||
vec3 grav_vel(float grav) {
|
||||
return vec3(0, 0, -grav * lifetime);
|
||||
}
|
||||
|
||||
float exp_scale(float factor) {
|
||||
return 1 / (1 - lifetime * factor);
|
||||
}
|
||||
|
||||
float linear_scale(float factor) {
|
||||
return lifetime * factor;
|
||||
}
|
||||
|
||||
float percent() {
|
||||
return lifetime / inst_lifespan;
|
||||
}
|
||||
|
||||
float slow_end(float factor) {
|
||||
return (1 + factor) * percent() / (percent() + factor);
|
||||
}
|
||||
|
||||
float slow_start(float factor) {
|
||||
return 1-(1 + factor) * (1-percent()) / ((1-percent()) + factor);
|
||||
}
|
||||
|
||||
float start_end(float from, float to) {
|
||||
return mix(from, to, lifetime / inst_lifespan);
|
||||
}
|
||||
|
||||
mat4 spin_in_axis(vec3 axis, float angle)
|
||||
{
|
||||
axis = normalize(axis);
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
float oc = 1.0 - c;
|
||||
|
||||
return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0,
|
||||
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0,
|
||||
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
mat4 identity() {
|
||||
return mat4(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1
|
||||
);
|
||||
}
|
||||
|
||||
vec3 perp_axis1(vec3 axis) {
|
||||
return normalize(vec3(axis.y + axis.z, -axis.x + axis.z, -axis.x - axis.y));
|
||||
}
|
||||
|
||||
vec3 perp_axis2(vec3 axis1, vec3 axis2) {
|
||||
return normalize(vec3(axis1.y * axis2.z - axis1.z * axis2.y, axis1.z * axis2.x - axis1.x * axis2.z, axis1.x * axis2.y - axis1.y * axis2.x));
|
||||
}
|
||||
|
||||
// Line is the axis of the spiral, it goes from the start position to the end position
|
||||
// Radius is the distance from the axis the particle is
|
||||
// Time function is some value that ideally goes from 0 to 1. When it is 0, it is as
|
||||
// the point (0, 0, 0), when it is 1, it is at the point provided by the coordinates of line
|
||||
// Frequency increases the frequency of rotation
|
||||
// Offset is an offset to the angle of the rotation
|
||||
vec3 spiral_motion(vec3 line, float radius, float time_function, float frequency, float offset) {
|
||||
vec3 axis2 = perp_axis1(line);
|
||||
vec3 axis3 = perp_axis2(line, axis2);
|
||||
|
||||
return line * time_function + vec3(
|
||||
radius * cos(frequency * time_function - offset) * axis2.x + radius * sin(frequency * time_function - offset) * axis3.x,
|
||||
radius * cos(frequency * time_function - offset) * axis2.y + radius * sin(frequency * time_function - offset) * axis3.y,
|
||||
radius * cos(frequency * time_function - offset) * axis2.z + radius * sin(frequency * time_function - offset) * axis3.z);
|
||||
}
|
||||
|
||||
void main() {
|
||||
float rand0 = hash(vec4(inst_entropy + 0));
|
||||
float rand1 = hash(vec4(inst_entropy + 1));
|
||||
float rand2 = hash(vec4(inst_entropy + 2));
|
||||
float rand3 = hash(vec4(inst_entropy + 3));
|
||||
float rand4 = hash(vec4(inst_entropy + 4));
|
||||
float rand5 = hash(vec4(inst_entropy + 5));
|
||||
float rand6 = hash(vec4(inst_entropy + 6));
|
||||
float rand7 = hash(vec4(inst_entropy + 7));
|
||||
float rand8 = hash(vec4(inst_entropy + 8));
|
||||
float rand9 = hash(vec4(inst_entropy + 9));
|
||||
|
||||
vec3 start_pos = inst_pos - focus_off.xyz;
|
||||
|
||||
Attr attr;
|
||||
f_reflect = 1.0;
|
||||
|
||||
switch(inst_mode) {
|
||||
case SMOKE:
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
vec3(rand2 * 0.02, rand3 * 0.02, 1.0 + rand4 * 0.1)
|
||||
),
|
||||
vec3(linear_scale(0.5)),
|
||||
vec4(vec3(0.8, 0.8, 1) * 0.5, start_end(1.0, 0.0)),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 0.5)
|
||||
);
|
||||
break;
|
||||
case FIRE:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0.0),
|
||||
vec3(rand2 * 0.1, rand3 * 0.1, 2.0 + rand4 * 1.0)
|
||||
),
|
||||
vec3(1.0),
|
||||
vec4(2, 1.5 + rand5 * 0.5, 0, start_end(1.0, 0.0)),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3)
|
||||
);
|
||||
break;
|
||||
case FIRE_BOWL:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(normalize(vec2(rand0, rand1)) * 0.1, 0.6),
|
||||
vec3(rand2 * 0.2, rand3 * 0.5, 0.8 + rand4 * 0.5)
|
||||
),
|
||||
vec3(0.2), // Size
|
||||
vec4(2, 1.5 + rand5 * 0.5, 0, start_end(1.0, 0.0)), // Colour
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3)
|
||||
);
|
||||
break;
|
||||
case GUN_POWDER_SPARK:
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
normalize(vec3(rand0, rand1, rand3)) * 0.3,
|
||||
normalize(vec3(rand4, rand5, rand6)) * 4.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(1.0),
|
||||
vec4(3.5, 3 + rand7, 0, 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
case SHRAPNEL:
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand4, rand5, rand6)) * 20.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(1),
|
||||
vec4(vec3(0.25), 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
case BIG_SHRAPNEL:
|
||||
float brown_color = 0.05 + 0.1 * rand1;
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand4, rand5, rand6)) * 15.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(5 * (1 - percent())),
|
||||
vec4(vec3(brown_color, brown_color / 2, 0), 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
case FIREWORK_BLUE:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand1, rand2, rand3)) * 40.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(3.0 + rand0),
|
||||
vec4(vec3(0, 0, 2), 1),
|
||||
identity()
|
||||
);
|
||||
break;
|
||||
case FIREWORK_GREEN:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand1, rand2, rand3)) * 40.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(3.0 + rand0),
|
||||
vec4(vec3(0, 2, 0), 1),
|
||||
identity()
|
||||
);
|
||||
break;
|
||||
case FIREWORK_PURPLE:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand1, rand2, rand3)) * 40.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(3.0 + rand0),
|
||||
vec4(vec3(2, 0, 2), 1),
|
||||
identity()
|
||||
);
|
||||
break;
|
||||
case FIREWORK_RED:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand1, rand2, rand3)) * 40.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(3.0 + rand0),
|
||||
vec4(vec3(2, 0, 0), 1),
|
||||
identity()
|
||||
);
|
||||
break;
|
||||
case FIREWORK_WHITE:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand1, rand2, rand3)) * 40.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(3.0 + rand0),
|
||||
vec4(vec3(2, 2, 2), 1),
|
||||
identity()
|
||||
);
|
||||
break;
|
||||
case FIREWORK_YELLOW:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand1, rand2, rand3)) * 40.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3(3.0 + rand0),
|
||||
vec4(vec3(2, 2, 0), 1),
|
||||
identity()
|
||||
);
|
||||
break;
|
||||
case LEAF:
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
vec3(0, 0, -2)
|
||||
) + vec3(sin(lifetime), sin(lifetime + 0.7), sin(lifetime * 0.5)) * 2.0,
|
||||
vec3(4),
|
||||
vec4(vec3(0.2 + rand7 * 0.2, 0.2 + (0.25 + rand6 * 0.5) * 0.3, 0) * (0.75 + rand1 * 0.5), 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5)
|
||||
);
|
||||
break;
|
||||
case SNOW:
|
||||
float height = mix(-4, 60, pow(start_end(1, 0), 3));
|
||||
float wind_speed = (inst_pos.z - 2000) * 0.025;
|
||||
vec3 offset = linear_motion(vec3(0), vec3(1, 1, 0) * wind_speed);
|
||||
float end_alt = alt_at(start_pos.xy + offset.xy);
|
||||
attr = Attr(
|
||||
offset + vec3(0, 0, end_alt - start_pos.z + height) + vec3(sin(lifetime), sin(lifetime + 0.7), sin(lifetime * 0.5)) * 3,
|
||||
vec3(mix(4, 0, pow(start_end(1, 0), 4))),
|
||||
vec4(1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5)
|
||||
);
|
||||
break;
|
||||
case FIREFLY:
|
||||
float raise = pow(sin(3.1416 * lifetime / inst_lifespan), 0.2);
|
||||
attr = Attr(
|
||||
vec3(0, 0, raise * 5.0) + vec3(
|
||||
sin(lifetime * 1.0 + rand0) + sin(lifetime * 7.0 + rand3) * 0.3,
|
||||
sin(lifetime * 3.0 + rand1) + sin(lifetime * 8.0 + rand4) * 0.3,
|
||||
sin(lifetime * 2.0 + rand2) + sin(lifetime * 9.0 + rand5) * 0.3
|
||||
),
|
||||
vec3(raise),
|
||||
vec4(vec3(10.3, 9, 1.5), 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5)
|
||||
);
|
||||
break;
|
||||
case BEE:
|
||||
float lower = pow(sin(3.1416 * lifetime / inst_lifespan), 0.2);
|
||||
attr = Attr(
|
||||
vec3(0, 0, lower * -0.5) + vec3(
|
||||
sin(lifetime * 2.0 + rand0) + sin(lifetime * 9.0 + rand3) * 0.3,
|
||||
sin(lifetime * 3.0 + rand1) + sin(lifetime * 10.0 + rand4) * 0.3,
|
||||
sin(lifetime * 4.0 + rand2) + sin(lifetime * 11.0 + rand5) * 0.3
|
||||
) * 0.5,
|
||||
vec3(lower),
|
||||
vec4(vec3(1, 0.7, 0), 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5)
|
||||
);
|
||||
break;
|
||||
case GROUND_SHOCKWAVE:
|
||||
attr = Attr(
|
||||
vec3(0.0),
|
||||
vec3(11.0, 11.0, (33.0 * rand0 * sin(2.0 * lifetime * 3.14 * 2.0))) / 3,
|
||||
vec4(vec3(0.32 + (rand0 * 0.04), 0.22 + (rand1 * 0.03), 0.05 + (rand2 * 0.01)), 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
case ENERGY_HEALING:
|
||||
f_reflect = 0.0;
|
||||
float spiral_radius = start_end(1 - pow(abs(rand5), 5), 1) * length(inst_dir);
|
||||
attr = Attr(
|
||||
spiral_motion(vec3(0, 0, rand3 + 1), spiral_radius, lifetime, abs(rand0), rand1 * 2 * PI) + vec3(0, 0, rand2),
|
||||
vec3(6 * abs(rand4) * (1 - slow_start(2)) * pow(spiral_radius / length(inst_dir), 0.5)),
|
||||
vec4(vec3(0, 1.7, 0.7) * 3, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3)
|
||||
);
|
||||
break;
|
||||
case LIFESTEAL_BEAM:
|
||||
f_reflect = 0.0;
|
||||
float green_col = 0.2 + 1.4 * sin(tick.x * 5 + lifetime * 5);
|
||||
float purple_col = 1.2 + 0.1 * sin(tick.x * 3 - lifetime * 3) - max(green_col, 1) + 1;
|
||||
attr = Attr(
|
||||
spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time),
|
||||
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))),
|
||||
vec4(vec3(purple_col, green_col, 0.75 * purple_col) * 3, 1),
|
||||
spin_in_axis(inst_dir, tick.z)
|
||||
);
|
||||
break;
|
||||
case ENERGY_NATURE:
|
||||
f_reflect = 0.0;
|
||||
spiral_radius = start_end(1 - pow(abs(rand5), 5), 1) * length(inst_dir);
|
||||
attr = Attr(
|
||||
spiral_motion(vec3(0, 0, rand3 + 1), spiral_radius, lifetime, abs(rand0), rand1 * 2 * PI) + vec3(0, 0, rand2),
|
||||
vec3(6 * abs(rand4) * (1 - slow_start(2)) * pow(spiral_radius / length(inst_dir), 0.5)),
|
||||
vec4(vec3(0, 1.7, 1.3), 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3)
|
||||
);
|
||||
break;
|
||||
case FLAMETHROWER:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (percent() + 2) * 0.1,
|
||||
vec3((2.5 * (1 - slow_start(0.2)))),
|
||||
vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case EXPLOSION:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
inst_dir * ((rand0+1.0)/2 + 0.4) * slow_end(2.0) + 0.3 * grav_vel(earth_gravity),
|
||||
vec3((3 * (1 - slow_start(0.1)))),
|
||||
vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case ICE:
|
||||
f_reflect = 0.0; // Ice doesn't reflect to look like magic
|
||||
float ice_color = 1.9 + rand5 * 0.3;
|
||||
attr = Attr(
|
||||
inst_dir * ((rand0+1.0)/2 + 0.4) * slow_end(2.0) + 0.3 * grav_vel(earth_gravity),
|
||||
vec3((5 * (1 - slow_start(.1)))),
|
||||
vec4(0.8 * ice_color, 0.9 * ice_color, ice_color, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case FIRE_SHOCKWAVE:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
attr = Attr(
|
||||
vec3(rand0, rand1, lifetime * 10 + rand2),
|
||||
vec3((5 * (1 - slow_start(0.5)))),
|
||||
vec4(3, 1.6 + rand5 * 0.3 - 0.4 * percent(), 0.2, 1),
|
||||
spin_in_axis(vec3(rand3, rand4, rand5), rand6)
|
||||
);
|
||||
break;
|
||||
case CULTIST_FLAME:
|
||||
f_reflect = 0.0; // Fire doesn't reflect light, it emits it
|
||||
float purp_color = 0.9 + 0.3 * rand3;
|
||||
attr = Attr(
|
||||
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (percent() + 2) * 0.1,
|
||||
vec3((3.5 * (1 - slow_start(0.2)))),
|
||||
vec4(purp_color, 0.0, purp_color, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case STATIC_SMOKE:
|
||||
attr = Attr(
|
||||
vec3(0),
|
||||
vec3((0.5 * (1 - slow_start(0.8)))),
|
||||
vec4(1.0),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), rand9)
|
||||
);
|
||||
break;
|
||||
case BLOOD:
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand4, rand5, rand6)) * 5.0 + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3((2.0 * (1 - slow_start(0.8)))),
|
||||
vec4(1, 0, 0, 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
case ENRAGED:
|
||||
f_reflect = 0.0;
|
||||
float red_color = 1.2 + 0.3 * rand3;
|
||||
attr = Attr(
|
||||
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (percent() + 2) * 0.1,
|
||||
vec3((3.5 * (1 - slow_start(0.2)))),
|
||||
vec4(red_color, 0.0, 0.0, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case LASER:
|
||||
f_reflect = 0.0;
|
||||
vec3 perp_axis = normalize(cross(inst_dir, vec3(0.0, 0.0, 1.0)));
|
||||
offset = vec3(0.0);
|
||||
if (rand0 > 0.0) {
|
||||
offset = perp_axis * 0.5;
|
||||
} else {
|
||||
offset = perp_axis * -0.5;
|
||||
}
|
||||
attr = Attr(
|
||||
inst_dir * percent() + offset,
|
||||
vec3(1.0, 1.0, 50.0),
|
||||
vec4(vec3(2.0, 0.0, 0.0), 1),
|
||||
spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0)
|
||||
);
|
||||
break;
|
||||
case BUBBLES:
|
||||
f_reflect = 0.0; // Magic water doesn't reflect light, it emits it
|
||||
float blue_color = 1.5 + 0.2 * rand3 + 1.5 * max(floor(rand4 + 0.3), 0.0);
|
||||
float size = 8.0 * (1 - slow_start(0.1)) * slow_end(0.15);
|
||||
attr = Attr(
|
||||
(inst_dir * slow_end(1.5)) + vec3(rand0, rand1, rand2) * (percent() + 2) * 0.1,
|
||||
vec3(size),
|
||||
vec4(0.5 * blue_color, 0.75 * blue_color, blue_color, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case WATER:
|
||||
f_reflect = 0.0; // Magic water doesn't reflect light, it emits it
|
||||
blue_color = 1.25 + 0.2 * rand3 + 1.75 * max(floor(rand4 + 0.15), 0.0);
|
||||
size = 8.0 * (1 - slow_start(0.1)) * slow_end(0.15);
|
||||
attr = Attr(
|
||||
(inst_dir * slow_end(0.2)) + vec3(rand0, rand1, rand2) * 0.5,
|
||||
vec3(size),
|
||||
vec4(0.5 * blue_color, 0.9 * blue_color, blue_color, 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 5 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case ICE_SPIKES:
|
||||
f_reflect = 0.0; // Ice doesn't reflect to look like magic
|
||||
ice_color = 1.7 + rand5 * 0.2;
|
||||
attr = Attr(
|
||||
vec3(0.0),
|
||||
vec3(11.0, 11.0, 11.0 * length(inst_dir) * 2.0 * (0.5 - abs(0.5 - slow_end(0.5)))) / 3,
|
||||
vec4(0.8 * ice_color, 0.9 * ice_color, ice_color, 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
case DRIP:
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
normalize(vec3(rand4, rand5, rand6)) + grav_vel(earth_gravity)
|
||||
),
|
||||
vec3((2.0 * (1 - slow_start(0.2)))),
|
||||
vec4(1, 1, 0, 1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
case TORNADO:
|
||||
f_reflect = 0.0;
|
||||
attr = Attr(
|
||||
spiral_motion(vec3(0, 0, 5), abs(rand0) + abs(rand1) * percent() * 3.0, percent(), 15.0 * abs(rand2), rand3),
|
||||
vec3((2.5 * (1 - slow_start(0.05)))),
|
||||
vec4(vec3(1.2 + 0.5 * percent()), 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
case DEATH:
|
||||
f_reflect = 0.0;
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(0),
|
||||
vec3(rand2 * 0.02, rand3 * 0.02, 2.0 + rand4 * 0.6)
|
||||
),
|
||||
vec3((1.2 * (1 - slow_start(.1)))),
|
||||
vec4(vec3(1.2 + 0.5 * percent()), 1),
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
attr = Attr(
|
||||
linear_motion(
|
||||
vec3(rand0 * 0.25, rand1 * 0.25, 1.7 + rand5),
|
||||
vec3(rand2 * 0.1, rand3 * 0.1, 1.0 + rand4 * 0.5)
|
||||
),
|
||||
vec3(exp_scale(-0.2)) * rand0,
|
||||
vec4(1),
|
||||
spin_in_axis(vec3(1,0,0),0)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// Temporary: use shrinking particles as a substitute for fading ones
|
||||
attr.scale *= pow(attr.col.a, 0.25);
|
||||
|
||||
f_pos = start_pos + (v_pos * attr.scale * SCALE * mat3(attr.rot) + attr.offs);
|
||||
|
||||
#ifdef EXPERIMENTAL_CURVEDWORLD
|
||||
f_pos.z -= pow(distance(f_pos.xy + focus_off.xy, focus_pos.xy + focus_off.xy) * 0.05, 2);
|
||||
#endif
|
||||
|
||||
// First 3 normals are negative, next 3 are positive
|
||||
// TODO: Make particle normals match orientation
|
||||
vec4 normals[6] = vec4[](vec4(-1,0,0,0), vec4(1,0,0,0), vec4(0,-1,0,0), vec4(0,1,0,0), vec4(0,0,-1,0), vec4(0,0,1,0));
|
||||
f_norm =
|
||||
// inst_pos *
|
||||
normalize(((normals[(v_norm_ao >> 0) & 0x7u]) * attr.rot).xyz);
|
||||
|
||||
//vec3 col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0;
|
||||
f_col = vec4(attr.col.rgb, attr.col.a);
|
||||
|
||||
gl_Position =
|
||||
all_mat *
|
||||
vec4(f_pos, 1);
|
||||
}
|
||||
on = 0)
|
||||
in vec3 v_pos;
|
||||
|
||||
layout (std140, set = 1, binding = 5)
|
||||
uniform u_locals {
|
||||
vec4 w_pos;
|
||||
vec4 w_color;
|
||||
vec4 w_ori;
|
||||
};
|
||||
|
||||
layout (location = 0)
|
||||
out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = w_color;
|
||||
|
||||
// Build rotation matrix
|
||||
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Rotation_matrices
|
||||
mat3 rotation_matrix;
|
||||
float q0 = w_ori[3];
|
||||
float q1 = w_ori[0];
|
||||
float q2 = w_ori[1];
|
||||
float q3 = w_ori[2];
|
||||
|
||||
float r00 = 1 - 2 * (pow(q2, 2) + pow(q3, 2));
|
||||
float r01 = 2 * (q1 * q2 - q0 * q3);
|
||||
float r02 = 2 * (q0 * q2 + q1 * q3);
|
||||
rotation_matrix[0] = vec3(r00, r01, r02);
|
||||
|
||||
float r10 = 2 * (q1 * q2 + q0 * q3);
|
||||
float r11 = 1 - 2 * (pow(q1, 2) + pow(q3, 2));
|
||||
float r12 = 2 * (q2 * q3 - q0 * q1);
|
||||
rotation_matrix[1] = vec3(r10, r11, r12);
|
||||
|
||||
float r20 = 2 * (q1 * q3 - q0 * q2);
|
||||
float r21 = 2 * (q0 * q1 + q2 * q3);
|
||||
float r22 = 1 - 2 * (pow(q1, 2) + pow(q2, 2));
|
||||
rotation_matrix[2] = vec3(r20, r21, r22);
|
||||
|
||||
gl_Position = all_mat * vec4((v_pos * rotation_matrix + w_pos.xyz) - focus_off.xyz, 1);
|
||||
}
|
@ -28,6 +28,7 @@ pub use self::{
|
||||
fluid::Vertex as FluidVertex,
|
||||
lod_terrain::{LodData, Vertex as LodTerrainVertex},
|
||||
particle::{Instance as ParticleInstance, Vertex as ParticleVertex},
|
||||
trail::{Instance as TrailInstance, Vertex as TrailVertex},
|
||||
postprocess::Locals as PostProcessLocals,
|
||||
shadow::{Locals as ShadowLocals, PointLightMatrix},
|
||||
skybox::{create_mesh as create_skybox_mesh, Vertex as SkyboxVertex},
|
||||
@ -46,7 +47,7 @@ pub use self::{
|
||||
},
|
||||
renderer::{
|
||||
drawer::{
|
||||
DebugDrawer, Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, ParticleDrawer,
|
||||
DebugDrawer, Drawer, FigureDrawer, FigureShadowDrawer, FirstPassDrawer, ParticleDrawer, TrailDrawer,
|
||||
PreparedUiDrawer, SecondPassDrawer, ShadowPassDrawer, SpriteDrawer, TerrainDrawer,
|
||||
TerrainShadowDrawer, ThirdPassDrawer, UiDrawer,
|
||||
},
|
||||
|
@ -11,6 +11,7 @@ pub mod shadow;
|
||||
pub mod skybox;
|
||||
pub mod sprite;
|
||||
pub mod terrain;
|
||||
pub mod trail;
|
||||
pub mod ui;
|
||||
|
||||
use super::{Consts, Texture};
|
||||
|
187
voxygen/src/render/pipelines/trail.rs
Normal file
187
voxygen/src/render/pipelines/trail.rs
Normal file
@ -0,0 +1,187 @@
|
||||
use super::super::{AaMode, GlobalsLayouts, Vertex as VertexTrait};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use std::mem;
|
||||
use vek::*;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||
pub struct Vertex {
|
||||
pub pos: [f32; 3],
|
||||
// ____BBBBBBBBGGGGGGGGRRRRRRRR
|
||||
// col: u32 = "v_col",
|
||||
// ...AANNN
|
||||
// A = AO
|
||||
// N = Normal
|
||||
norm_ao: u32,
|
||||
}
|
||||
|
||||
impl Vertex {
|
||||
#[allow(clippy::collapsible_else_if)]
|
||||
pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self {
|
||||
let norm_bits = if norm.x != 0.0 {
|
||||
if norm.x < 0.0 { 0 } else { 1 }
|
||||
} else if norm.y != 0.0 {
|
||||
if norm.y < 0.0 { 2 } else { 3 }
|
||||
} else {
|
||||
if norm.z < 0.0 { 4 } else { 5 }
|
||||
};
|
||||
|
||||
Self {
|
||||
pos: pos.into_array(),
|
||||
norm_ao: norm_bits,
|
||||
}
|
||||
}
|
||||
|
||||
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
|
||||
const ATTRIBUTES: [wgpu::VertexAttribute; 2] =
|
||||
wgpu::vertex_attr_array![0 => Float32x3, 1 => Uint32];
|
||||
wgpu::VertexBufferLayout {
|
||||
array_stride: Self::STRIDE,
|
||||
step_mode: wgpu::InputStepMode::Vertex,
|
||||
attributes: &ATTRIBUTES,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexTrait for Vertex {
|
||||
const QUADS_INDEX: Option<wgpu::IndexFormat> = Some(wgpu::IndexFormat::Uint16);
|
||||
const STRIDE: wgpu::BufferAddress = mem::size_of::<Self>() as wgpu::BufferAddress;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||
pub struct Instance {
|
||||
// created_at time, so we can calculate time relativity, needed for relative animation.
|
||||
// can save 32 bits per instance, for trails that are not relatively animated.
|
||||
inst_time: f32,
|
||||
|
||||
// The lifespan in seconds of the trail
|
||||
inst_lifespan: f32,
|
||||
|
||||
// The two positions that define where the line of the object making the trail, e.g. sword tip and sword hilt
|
||||
inner_pos: [f32; 3],
|
||||
outer_pos: [f32; 3],
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
pub fn new(
|
||||
inst_time: f64,
|
||||
lifespan: f32,
|
||||
inner_pos: Vec3<f32>,
|
||||
outer_pos: Vec3<f32>,
|
||||
) -> Self {
|
||||
Self {
|
||||
inst_time: inst_time as f32,
|
||||
inst_lifespan: lifespan,
|
||||
inner_pos: inner_pos.into_array(),
|
||||
outer_pos: outer_pos.into_array(),
|
||||
}
|
||||
}
|
||||
|
||||
fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
|
||||
const ATTRIBUTES: [wgpu::VertexAttribute; 4] = wgpu::vertex_attr_array![2 => Float32, 3 => Float32, 4 => Float32x3, 5 => Float32x3];
|
||||
wgpu::VertexBufferLayout {
|
||||
array_stride: mem::size_of::<Self>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::InputStepMode::Instance,
|
||||
attributes: &ATTRIBUTES,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Instance {
|
||||
fn default() -> Self { Self::new(0.0, 0.0, Vec3::zero(), Vec3::zero()) }
|
||||
}
|
||||
|
||||
pub struct TrailPipeline {
|
||||
pub pipeline: wgpu::RenderPipeline,
|
||||
}
|
||||
|
||||
impl TrailPipeline {
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
vs_module: &wgpu::ShaderModule,
|
||||
fs_module: &wgpu::ShaderModule,
|
||||
global_layout: &GlobalsLayouts,
|
||||
aa_mode: AaMode,
|
||||
) -> Self {
|
||||
common_base::span!(_guard, "TrailPipeline::new");
|
||||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Trail pipeline layout"),
|
||||
push_constant_ranges: &[],
|
||||
bind_group_layouts: &[&global_layout.globals, &global_layout.shadow_textures],
|
||||
});
|
||||
|
||||
let samples = match aa_mode {
|
||||
AaMode::None | AaMode::Fxaa => 1,
|
||||
AaMode::MsaaX4 => 4,
|
||||
AaMode::MsaaX8 => 8,
|
||||
AaMode::MsaaX16 => 16,
|
||||
};
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Trail pipeline"),
|
||||
layout: Some(&render_pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: vs_module,
|
||||
entry_point: "main",
|
||||
buffers: &[Vertex::desc(), Instance::desc()],
|
||||
},
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
clamp_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: wgpu::TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::GreaterEqual,
|
||||
stencil: wgpu::StencilState {
|
||||
front: wgpu::StencilFaceState::IGNORE,
|
||||
back: wgpu::StencilFaceState::IGNORE,
|
||||
read_mask: !0,
|
||||
write_mask: !0,
|
||||
},
|
||||
bias: wgpu::DepthBiasState {
|
||||
constant: 0,
|
||||
slope_scale: 0.0,
|
||||
clamp: 0.0,
|
||||
},
|
||||
}),
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: samples,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: fs_module,
|
||||
entry_point: "main",
|
||||
targets: &[wgpu::ColorTargetState {
|
||||
// TODO: use a constant and/or pass in this format on pipeline construction
|
||||
format: wgpu::TextureFormat::Rgba16Float,
|
||||
blend: Some(wgpu::BlendState {
|
||||
color: wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
alpha: wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::One,
|
||||
dst_factor: wgpu::BlendFactor::One,
|
||||
operation: wgpu::BlendOperation::Add,
|
||||
},
|
||||
}),
|
||||
write_mask: wgpu::ColorWrite::ALL,
|
||||
}],
|
||||
}),
|
||||
});
|
||||
|
||||
Self {
|
||||
pipeline: render_pipeline,
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ use super::{
|
||||
model::{DynamicModel, Model, SubModel},
|
||||
pipelines::{
|
||||
blit, bloom, clouds, debug, figure, fluid, lod_terrain, particle, shadow, skybox,
|
||||
sprite, terrain, ui, ColLights, GlobalsBindGroup, ShadowTexturesBindGroup,
|
||||
sprite, terrain, ui, ColLights, GlobalsBindGroup, ShadowTexturesBindGroup, trail,
|
||||
},
|
||||
},
|
||||
Renderer, ShadowMap, ShadowMapRenderer,
|
||||
@ -738,6 +738,15 @@ impl<'pass> FirstPassDrawer<'pass> {
|
||||
ParticleDrawer { render_pass }
|
||||
}
|
||||
|
||||
pub fn draw_trails(&mut self) -> TrailDrawer<'_, 'pass> {
|
||||
let mut render_pass = self.render_pass.scope("trails", self.borrow.device);
|
||||
|
||||
render_pass.set_pipeline(&self.pipelines.trail.pipeline);
|
||||
set_quad_index_buffer::<trail::Vertex>(&mut render_pass, self.borrow);
|
||||
|
||||
TrailDrawer { render_pass }
|
||||
}
|
||||
|
||||
pub fn draw_sprites<'data: 'pass>(
|
||||
&mut self,
|
||||
globals: &'data sprite::SpriteGlobalsBindGroup,
|
||||
@ -863,6 +872,25 @@ impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TrailDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||
}
|
||||
|
||||
impl<'pass_ref, 'pass: 'pass_ref> TrailDrawer<'pass_ref, 'pass> {
|
||||
pub fn draw<'data: 'pass>(
|
||||
&mut self,
|
||||
model: &'data Model<trail::Vertex>,
|
||||
instances: &'data Instances<trail::Instance>,
|
||||
) {
|
||||
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
|
||||
self.render_pass
|
||||
.set_vertex_buffer(0, instances.buf().slice(..));
|
||||
self.render_pass
|
||||
// TODO: since we cast to u32 maybe this should returned by the len/count functions?
|
||||
.draw_indexed(0..model.len() as u32 / 4 * 6, 0, 0..instances.count() as u32);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpriteDrawer<'pass_ref, 'pass: 'pass_ref> {
|
||||
render_pass: Scope<'pass_ref, wgpu::RenderPass<'pass>>,
|
||||
globals: &'pass GlobalsBindGroup,
|
||||
|
@ -2,7 +2,7 @@ use super::{
|
||||
super::{
|
||||
pipelines::{
|
||||
blit, bloom, clouds, debug, figure, fluid, lod_terrain, particle, postprocess, shadow,
|
||||
skybox, sprite, terrain, ui,
|
||||
skybox, sprite, terrain, ui, trail,
|
||||
},
|
||||
AaMode, BloomMode, CloudMode, FluidMode, LightingMode, PipelineModes, RenderError,
|
||||
ShadowMode,
|
||||
@ -20,6 +20,7 @@ pub struct Pipelines {
|
||||
pub fluid: fluid::FluidPipeline,
|
||||
pub lod_terrain: lod_terrain::LodTerrainPipeline,
|
||||
pub particle: particle::ParticlePipeline,
|
||||
pub trail: trail::TrailPipeline,
|
||||
pub clouds: clouds::CloudsPipeline,
|
||||
pub bloom: Option<bloom::BloomPipelines>,
|
||||
pub postprocess: postprocess::PostProcessPipeline,
|
||||
@ -40,6 +41,7 @@ pub struct IngamePipelines {
|
||||
fluid: fluid::FluidPipeline,
|
||||
lod_terrain: lod_terrain::LodTerrainPipeline,
|
||||
particle: particle::ParticlePipeline,
|
||||
trail: trail::TrailPipeline,
|
||||
clouds: clouds::CloudsPipeline,
|
||||
pub bloom: Option<bloom::BloomPipelines>,
|
||||
postprocess: postprocess::PostProcessPipeline,
|
||||
@ -76,6 +78,7 @@ impl Pipelines {
|
||||
fluid: ingame.fluid,
|
||||
lod_terrain: ingame.lod_terrain,
|
||||
particle: ingame.particle,
|
||||
trail: ingame.trail,
|
||||
clouds: ingame.clouds,
|
||||
bloom: ingame.bloom,
|
||||
postprocess: ingame.postprocess,
|
||||
@ -105,6 +108,8 @@ struct ShaderModules {
|
||||
sprite_frag: wgpu::ShaderModule,
|
||||
particle_vert: wgpu::ShaderModule,
|
||||
particle_frag: wgpu::ShaderModule,
|
||||
trail_vert: wgpu::ShaderModule,
|
||||
trail_frag: wgpu::ShaderModule,
|
||||
ui_vert: wgpu::ShaderModule,
|
||||
ui_frag: wgpu::ShaderModule,
|
||||
lod_terrain_vert: wgpu::ShaderModule,
|
||||
@ -290,6 +295,8 @@ impl ShaderModules {
|
||||
sprite_frag: create_shader("sprite-frag", ShaderKind::Fragment)?,
|
||||
particle_vert: create_shader("particle-vert", ShaderKind::Vertex)?,
|
||||
particle_frag: create_shader("particle-frag", ShaderKind::Fragment)?,
|
||||
trail_vert: create_shader("trail-vert", ShaderKind::Vertex)?,
|
||||
trail_frag: create_shader("trail-frag", ShaderKind::Fragment)?,
|
||||
ui_vert: create_shader("ui-vert", ShaderKind::Vertex)?,
|
||||
ui_frag: create_shader("ui-frag", ShaderKind::Fragment)?,
|
||||
lod_terrain_vert: create_shader("lod-terrain-vert", ShaderKind::Vertex)?,
|
||||
@ -407,7 +414,7 @@ fn create_interface_pipelines(
|
||||
fn create_ingame_and_shadow_pipelines(
|
||||
needs: PipelineNeeds,
|
||||
pool: &rayon::ThreadPool,
|
||||
tasks: [Task; 14],
|
||||
tasks: [Task; 15],
|
||||
) -> IngameAndShadowPipelines {
|
||||
prof_span!(_guard, "create_ingame_and_shadow_pipelines");
|
||||
|
||||
@ -427,6 +434,7 @@ fn create_ingame_and_shadow_pipelines(
|
||||
fluid_task,
|
||||
sprite_task,
|
||||
particle_task,
|
||||
trail_task,
|
||||
lod_terrain_task,
|
||||
clouds_task,
|
||||
bloom_task,
|
||||
@ -552,6 +560,21 @@ fn create_ingame_and_shadow_pipelines(
|
||||
"particle pipeline creation",
|
||||
)
|
||||
};
|
||||
// Pipeline for rendering weapon trails
|
||||
let create_trail = || {
|
||||
trail_task.run(
|
||||
|| {
|
||||
trail::TrailPipeline::new(
|
||||
device,
|
||||
&shaders.trail_vert,
|
||||
&shaders.trail_frag,
|
||||
&layouts.global,
|
||||
pipeline_modes.aa,
|
||||
)
|
||||
},
|
||||
"trail pipeline creation",
|
||||
)
|
||||
};
|
||||
// Pipeline for rendering terrain
|
||||
let create_lod_terrain = || {
|
||||
lod_terrain_task.run(
|
||||
@ -695,7 +718,7 @@ fn create_ingame_and_shadow_pipelines(
|
||||
|
||||
let j1 = || pool.join(create_debug, || pool.join(create_skybox, create_figure));
|
||||
let j2 = || pool.join(create_terrain, || pool.join(create_fluid, create_bloom));
|
||||
let j3 = || pool.join(create_sprite, create_particle);
|
||||
let j3 = || pool.join(create_sprite, || pool.join(create_particle, create_trail));
|
||||
let j4 = || pool.join(create_lod_terrain, create_clouds);
|
||||
let j5 = || pool.join(create_postprocess, create_point_shadow);
|
||||
let j6 = || {
|
||||
@ -709,7 +732,7 @@ fn create_ingame_and_shadow_pipelines(
|
||||
let (
|
||||
(
|
||||
((debug, (skybox, figure)), (terrain, (fluid, bloom))),
|
||||
((sprite, particle), (lod_terrain, clouds)),
|
||||
((sprite, (particle, trail)), (lod_terrain, clouds)),
|
||||
),
|
||||
((postprocess, point_shadow), (terrain_directed_shadow, figure_directed_shadow)),
|
||||
) = pool.join(
|
||||
@ -724,6 +747,7 @@ fn create_ingame_and_shadow_pipelines(
|
||||
fluid,
|
||||
lod_terrain,
|
||||
particle,
|
||||
trail,
|
||||
clouds,
|
||||
bloom,
|
||||
postprocess,
|
||||
|
@ -6,6 +6,7 @@ pub mod math;
|
||||
pub mod particle;
|
||||
pub mod simple;
|
||||
pub mod terrain;
|
||||
pub mod trail;
|
||||
|
||||
pub use self::{
|
||||
camera::{Camera, CameraMode},
|
||||
@ -13,6 +14,7 @@ pub use self::{
|
||||
figure::FigureMgr,
|
||||
lod::Lod,
|
||||
particle::ParticleMgr,
|
||||
trail::TrailMgr,
|
||||
terrain::{SpriteRenderContextLazy, Terrain},
|
||||
};
|
||||
use crate::{
|
||||
@ -95,6 +97,7 @@ pub struct Scene {
|
||||
light_data: Vec<Light>,
|
||||
|
||||
particle_mgr: ParticleMgr,
|
||||
trail_mgr: TrailMgr,
|
||||
figure_mgr: FigureMgr,
|
||||
pub sfx_mgr: SfxMgr,
|
||||
music_mgr: MusicMgr,
|
||||
@ -115,6 +118,7 @@ pub struct SceneData<'a> {
|
||||
pub mouse_smoothing: bool,
|
||||
pub sprite_render_distance: f32,
|
||||
pub particles_enabled: bool,
|
||||
pub trails_enabled: bool,
|
||||
pub figure_lod_render_distance: f32,
|
||||
pub is_aiming: bool,
|
||||
}
|
||||
@ -305,6 +309,7 @@ impl Scene {
|
||||
select_pos: None,
|
||||
light_data: Vec::new(),
|
||||
particle_mgr: ParticleMgr::new(renderer),
|
||||
trail_mgr: TrailMgr::new(renderer),
|
||||
figure_mgr: FigureMgr::new(renderer),
|
||||
sfx_mgr: SfxMgr::default(),
|
||||
music_mgr: MusicMgr::default(),
|
||||
@ -327,6 +332,9 @@ impl Scene {
|
||||
/// Get a reference to the scene's particle manager.
|
||||
pub fn particle_mgr(&self) -> &ParticleMgr { &self.particle_mgr }
|
||||
|
||||
/// Get a reference to the scene's trail manager.
|
||||
pub fn trail_mgr(&self) -> &TrailMgr { &self.trail_mgr }
|
||||
|
||||
/// Get a reference to the scene's figure manager.
|
||||
pub fn figure_mgr(&self) -> &FigureMgr { &self.figure_mgr }
|
||||
|
||||
@ -547,6 +555,10 @@ impl Scene {
|
||||
self.particle_mgr
|
||||
.maintain(renderer, scene_data, &self.terrain, lights);
|
||||
|
||||
// Maintain the trails.
|
||||
self.trail_mgr
|
||||
.maintain(renderer, scene_data, &self.terrain);
|
||||
|
||||
// Update light constants
|
||||
lights.extend(
|
||||
(
|
||||
|
104
voxygen/src/scene/trail.rs
Normal file
104
voxygen/src/scene/trail.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use super::{SceneData, Terrain};
|
||||
use crate::{
|
||||
render::{
|
||||
Instances, TrailDrawer,
|
||||
TrailInstance, Renderer,
|
||||
},
|
||||
};
|
||||
use common::{
|
||||
terrain::TerrainChunk,
|
||||
};
|
||||
use common_base::span;
|
||||
use std::time::Duration;
|
||||
use vek::*;
|
||||
|
||||
pub struct TrailMgr {
|
||||
/// keep track of lifespans
|
||||
trails: Vec<Trail>,
|
||||
|
||||
/// GPU Instance Buffer
|
||||
instances: Instances<TrailInstance>,
|
||||
}
|
||||
|
||||
impl TrailMgr {
|
||||
pub fn new(renderer: &mut Renderer) -> Self {
|
||||
Self {
|
||||
trails: Vec::new(),
|
||||
instances: default_instances(renderer),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maintain(
|
||||
&mut self,
|
||||
renderer: &mut Renderer,
|
||||
scene_data: &SceneData,
|
||||
terrain: &Terrain<TerrainChunk>,
|
||||
) {
|
||||
span!(_guard, "maintain", "TrailMgr::maintain");
|
||||
if scene_data.trails_enabled {
|
||||
// remove dead Trails
|
||||
self.trails
|
||||
.retain(|p| p.alive_until > scene_data.state.get_time());
|
||||
|
||||
// add new Trails
|
||||
|
||||
self.upload_trails(renderer);
|
||||
} else {
|
||||
// remove all trail lifespans
|
||||
if !self.trails.is_empty() {
|
||||
self.trails.clear();
|
||||
self.upload_trails(renderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upload_trails(&mut self, renderer: &mut Renderer) {
|
||||
span!(_guard, "upload_trails", "TrailMgr::upload_trails");
|
||||
let all_cpu_instances = self
|
||||
.trails
|
||||
.iter()
|
||||
.map(|p| p.instance)
|
||||
.collect::<Vec<TrailInstance>>();
|
||||
|
||||
// TODO: optimise buffer writes
|
||||
let gpu_instances = renderer
|
||||
.create_instances(&all_cpu_instances)
|
||||
.expect("Failed to upload trail instances to the GPU!");
|
||||
|
||||
self.instances = gpu_instances;
|
||||
}
|
||||
|
||||
pub fn render<'a>(&'a self, drawer: &mut TrailDrawer<'_, 'a>, scene_data: &SceneData) {
|
||||
span!(_guard, "render", "TrailMgr::render");
|
||||
if scene_data.trails_enabled {
|
||||
drawer.draw(&self.instances);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trail_count(&self) -> usize { self.instances.count() }
|
||||
|
||||
pub fn trail_count_visible(&self) -> usize { self.instances.count() }
|
||||
}
|
||||
|
||||
fn default_instances(renderer: &mut Renderer) -> Instances<TrailInstance> {
|
||||
let empty_vec = Vec::new();
|
||||
|
||||
renderer
|
||||
.create_instances(&empty_vec)
|
||||
.expect("Failed to upload trail instances to the GPU!")
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Trail {
|
||||
alive_until: f64, // created_at + lifespan
|
||||
instance: TrailInstance,
|
||||
}
|
||||
|
||||
impl Trail {
|
||||
fn new(lifespan: Duration, time: f64, inner_pos: Vec3<f32>, outer_pos: Vec3<f32>)-> Self {
|
||||
Trail {
|
||||
alive_until: time + lifespan.as_secs_f64(),
|
||||
instance: TrailInstance::new(time, lifespan.as_secs_f32(), inner_pos, outer_pos),
|
||||
}
|
||||
}
|
||||
}
|
@ -1474,6 +1474,7 @@ impl PlayState for SessionState {
|
||||
sprite_render_distance: global_state.settings.graphics.sprite_render_distance
|
||||
as f32,
|
||||
particles_enabled: global_state.settings.graphics.particles_enabled,
|
||||
trails_enabled: global_state.settings.graphics.trails_enabled,
|
||||
figure_lod_render_distance: global_state
|
||||
.settings
|
||||
.graphics
|
||||
@ -1547,6 +1548,7 @@ impl PlayState for SessionState {
|
||||
sprite_render_distance: settings.graphics.sprite_render_distance as f32,
|
||||
figure_lod_render_distance: settings.graphics.figure_lod_render_distance as f32,
|
||||
particles_enabled: settings.graphics.particles_enabled,
|
||||
trails_enabled: settings.graphics.trails_enabled,
|
||||
is_aiming: self.is_aiming,
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@ pub struct GraphicsSettings {
|
||||
pub view_distance: u32,
|
||||
pub sprite_render_distance: u32,
|
||||
pub particles_enabled: bool,
|
||||
pub trails_enabled: bool,
|
||||
pub lossy_terrain_compression: bool,
|
||||
pub figure_lod_render_distance: u32,
|
||||
pub max_fps: Fps,
|
||||
@ -52,6 +53,7 @@ impl Default for GraphicsSettings {
|
||||
view_distance: 10,
|
||||
sprite_render_distance: 100,
|
||||
particles_enabled: true,
|
||||
trails_enabled: true,
|
||||
lossy_terrain_compression: false,
|
||||
figure_lod_render_distance: 300,
|
||||
max_fps: Fps::Max(60),
|
||||
|
Loading…
Reference in New Issue
Block a user