pimp up stage1 background

This commit is contained in:
Andrei Alexeyev 2019-12-05 18:45:32 +02:00
parent 229fe032b5
commit 23636c4ace
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
11 changed files with 250 additions and 64 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,3 @@
wrap_s = clamp
wrap_t = clamp

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 KiB

View file

@ -4,6 +4,11 @@
#include "interface/standard.glslh"
UNIFORM(1) float time;
UNIFORM(2) vec4 water_color;
UNIFORM(3) float wave_offset;
const vec4 reflection_color = vec4(0.5, 0.8, 0.8, 1.0);
const vec4 wave_color = vec4(0.8, 0.8, 1.0, 1.0);
// Based on https://www.shadertoy.com/view/Xl2XWz
@ -41,7 +46,7 @@ float warpedNoise(vec2 p) {
}
void main(void) {
vec2 uv = flip_native_to_bottomleft(texCoord - vec2(0, 2+time * 0.2)) * rot(-pi/4);
vec2 uv = flip_native_to_bottomleft(texCoord - vec2(0, wave_offset)) * rot(-pi/4);
float n = warpedNoise(uv * 4);
@ -52,11 +57,14 @@ void main(void) {
bump = bump * bump * 0.5;
bump2 = bump2 * bump2 * 0.5;
vec4 cmod = vec4(0.5, 0.8, 0.8, 1.0);
uv = flip_native_to_bottomleft(texCoord);
uv += 0.25 * vec2(bump, bump2);
uv = flip_bottomleft_to_native(uv);
fragColor = mix(cmod * texture(tex, uv), vec4(0.8, 0.8, 1.0, 1.0), (bump2 - bump * 0.25) * 0.05);
vec4 reflection = texture(tex, uv);
reflection.rgb = mix(reflection.rgb, water_color.rgb, reflection.a * 0.5);
reflection = reflection * reflection_color * 0.5;
vec4 surface = alphaCompose(water_color, reflection);
fragColor = mix(surface, wave_color, (bump2 - bump * 0.25) * 0.05);
}

View file

@ -46,7 +46,11 @@ DEFINE_EXTERN_TASK(common_move_ext) {
common_move_loop(ARGS.pos, ARGS.move_params);
}
complex common_wander(complex origin, double dist, Rect bounds) {
DEFINE_EXTERN_TASK(common_call_func) {
ARGS.func();
}
cmplx common_wander(cmplx origin, double dist, Rect bounds) {
int attempts = 32;
double angle;
complex dest;

View file

@ -32,7 +32,12 @@ DECLARE_EXTERN_TASK(
{ complex *pos; MoveParams *move_params; BoxedEntity ent; }
);
void common_move_loop(complex *restrict pos, MoveParams *restrict mp);
DECLARE_EXTERN_TASK(
common_call_func,
{ void (*func)(void); }
);
void common_move_loop(cmplx *restrict pos, MoveParams *restrict mp);
INLINE Rect viewport_bounds(double margin) {
return (Rect) {

View file

@ -24,6 +24,13 @@ uint64_t splitmix64(uint64_t *state) {
return z ^ (z >> 31);
}
uint32_t splitmix32(uint32_t *state) {
uint32_t z = (*state += 0x9e3779b9);
z = (z ^ (z >> 15)) * 0x85ebca6b;
z = (z ^ (z >> 13)) * 0xc2b2ae3d;
return z ^ (z >> 16);
}
uint64_t makeseed(void) {
static uint64_t s = 69;
return splitmix64(&s) ^ SDL_GetPerformanceCounter();

View file

@ -28,6 +28,7 @@ typedef struct rng_val {
} rng_val_t;
uint64_t splitmix64(uint64_t *state) attr_nonnull(1);
uint32_t splitmix32(uint32_t *state) attr_nonnull(1);
uint64_t makeseed(void);
void rng_init(RandomState *rng, uint64_t seed) attr_nonnull(1);

View file

@ -16,6 +16,8 @@
#include "stageutils.h"
#include "stagedraw.h"
#include "resource/model.h"
#include "util/glm.h"
#include "common_tasks.h"
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
@ -51,7 +53,20 @@ struct stage1_spells_s stage1_spells = {
},
};
static FBPair stage1_bg_fbpair;
static struct {
FBPair water_fbpair;
struct {
float near, near_target;
float far, far_target;
} fog;
struct {
float opacity, opacity_target;
} snow;
float pitch_target;
} stage1_bg;
#ifdef SPELL_BENCHMARK
AttackInfo stage1_spell_benchmark = {
@ -109,42 +124,54 @@ static void stage1_water_draw(vec3 pos) {
r_mat_mv_translate(0, stage_3d_context.cx[1] + 500, 0);
r_mat_mv_rotate(M_PI, 1, 0, 0);
static const Color water_color = { 0, 0.08, 0.08, 1 };
r_clear(CLEAR_COLOR, &water_color, 1);
r_mat_mv_push();
r_mat_mv_translate(0, -9000, 0);
r_mat_mv_rotate(M_PI/2, 1, 0, 0);
r_mat_mv_scale(3640*1.4, 1456*1.4, 1);
r_mat_mv_translate(0, -0.5, 0);
r_shader_standard();
r_uniform_sampler("tex", "stage1/horizon");
r_draw_quad();
r_mat_mv_pop();
r_state_push();
r_enable(RCAP_DEPTH_TEST);
r_depth_func(DEPTH_ALWAYS);
r_shader_standard_notex();
r_mat_mv_push();
r_mat_mv_scale(1200, 3000, 1);
r_color4(0, 0.1, 0.1, 1);
r_mat_mv_scale(80000, 80000, 1);
r_color(&water_color);
r_draw_quad();
r_color4(1, 1, 1, 1);
r_mat_mv_pop();
r_state_pop();
r_disable(RCAP_CULL_FACE);
r_disable(RCAP_DEPTH_TEST);
r_disable(RCAP_CULL_FACE);
Framebuffer *bg_fb = r_framebuffer_current();
FBPair *fbpair = &stage1_bg_fbpair;
FBPair *fbpair = &stage1_bg.water_fbpair;
r_framebuffer(fbpair->back);
r_mat_proj_push();
set_ortho(VIEWPORT_W, VIEWPORT_H);
r_mat_mv_push_identity();
float z = 0.75;
float zo = -0.05;
float hack = (stage_3d_context.crot[0] - 60) / 15.0;
float z = glm_lerp(0.75, 0.8, hack);
float zo = glm_lerp(-0.05, -0.3, hack);
r_mat_mv_translate(VIEWPORT_W * 0.5 * (1 - z), VIEWPORT_H * 0.5 * (1 - z), 0);
r_mat_mv_scale(z, z, 1);
r_clear(CLEAR_ALL, RGBA(0, 0.08, 0.08, 1), 1);
r_clear(CLEAR_ALL, RGBA(0, 0, 0, 0), 1);
r_shader("sprite_default");
ent_draw(stage1_draw_predicate);
r_mat_mv_push();
r_shader_standard_notex();
r_mat_mv_translate(VIEWPORT_W*0.5, VIEWPORT_H*0.5, 0);
r_mat_mv_scale(VIEWPORT_W/z, VIEWPORT_H/z, 1);
r_color4(0, 0.08, 0.08, 0.8);
r_draw_quad();
r_mat_mv_pop();
r_mat_mv_pop();
fbpair_swap(fbpair);
@ -152,6 +179,11 @@ static void stage1_water_draw(vec3 pos) {
int pp_quality = config_get_int(CONFIG_POSTPROCESS);
ShaderProgram *water_shader = r_shader_get("stage1_water");
r_uniform_float(r_shader_uniform(water_shader, "time"), 0.5 * global.frames / (float)FPS);
r_uniform_vec4_rgba(r_shader_uniform(water_shader, "water_color"), &water_color);
r_uniform_float(r_shader_uniform(water_shader, "wave_offset"), stage_3d_context.cx[1] / 2400.0);
if(pp_quality > 1) {
r_shader("blur5");
r_uniform_vec2("blur_resolution", VIEWPORT_W, VIEWPORT_H);
@ -187,21 +219,14 @@ static void stage1_water_draw(vec3 pos) {
}
r_mat_mv_push();
r_mat_mv_translate(0, 70, 0);
r_mat_mv_translate(0, 70 - 140 * hack, 0);
r_mat_mv_rotate(10 * DEG2RAD, 1, 0, 0);
r_mat_mv_scale(0.85 / (z + zo), -0.85 / (z + zo), 0.85);
r_mat_mv_translate(-VIEWPORT_W/2, 0, 0);
r_mat_mv_translate(-VIEWPORT_W/2, VIEWPORT_H/4 * hack, 0);
r_color4(1, 1, 1, 1);
draw_framebuffer_tex(fbpair->front, VIEWPORT_W, VIEWPORT_H);
r_mat_mv_pop();
r_shader_standard_notex();
r_mat_mv_push();
r_mat_mv_scale(1200,3000,1);
r_color4(0, 0.08, 0.08, 0.08);
r_draw_quad();
r_mat_mv_pop();
r_mat_mv_pop();
r_state_pop();
}
@ -214,40 +239,62 @@ static uint stage1_bg_pos(Stage3D *s3d, vec3 p, float maxrange) {
static void stage1_smoke_draw(vec3 pos) {
float d = fabsf(pos[1]-stage_3d_context.cx[1]);
float o = ((d-500)*(d-500))/1.5e7;
o *= 5 * pow((5000 - d) / 5000, 3);
if(o < 1.0f/255.0f) {
return;
}
float spin = 0.01 * sin(pos[1]*993.11);
r_state_push();
r_shader("sprite_default");
r_disable(RCAP_DEPTH_TEST);
r_cull(CULL_BACK);
r_mat_mv_push();
r_mat_mv_translate(pos[0]+200*sin(pos[1]), pos[1], pos[2]+200*sin(pos[1]/25.0));
r_mat_mv_translate(pos[0]+600*sin(pos[1]), pos[1], pos[2]+600*sin(pos[1]/25.0));
r_mat_mv_rotate(M_PI/2, -1, 0, 0);
r_mat_mv_scale(3.5, 2, 1);
r_mat_mv_rotate(global.frames * DEG2RAD, 0, 0, 1);
float o = ((d-500)*(d-500))/1.5e7;
r_mat_mv_scale(3.5*2, 2*1.5, 1);
r_mat_mv_rotate(global.frames * spin + M_PI * 2 * sin(pos[1]*321.23), 0, 0, 1);
r_draw_sprite(&(SpriteParams) {
.sprite = "stage1/fog",
.color = RGBA(0.8 * o, 0.8 * o, 0.8 * o, o * 0.5),
.color = RGBA(0.6 * o, 0.7 * o, 0.8 * o, o * 0.5),
});
r_mat_mv_pop();
r_state_pop();
}
static uint stage1_smoke_pos(Stage3D *s3d, vec3 p, float maxrange) {
vec3 q = {0,0,-300};
vec3 r = {0,300,0};
vec3 q = {0,0,800};
vec3 r = {0,200,0};
return linear3dpos(s3d, p, maxrange/2.0, q, r);
}
static bool stage1_fog(Framebuffer *fb) {
r_shader("zbuf_fog");
r_uniform_sampler("depth", r_framebuffer_get_attachment(fb, FRAMEBUFFER_ATTACH_DEPTH));
r_uniform_vec4("fog_color", 0.78, 0.8, 0.85, 1.0);
r_uniform_float("start", stage1_bg.fog.near);
r_uniform_float("end", stage1_bg.fog.far);
r_uniform_float("exponent", 1.0);
r_uniform_float("sphereness", 0.2);
draw_framebuffer_tex(fb, VIEWPORT_W, VIEWPORT_H);
r_shader_standard();
return true;
}
static inline uint32_t floathash(float f) {
return (union { uint32_t i; float f; }){ .f = f }.i;
uint32_t bits = float_to_bits(f);
return splitmix32(&bits);
}
static void stage1_waterplants_draw(vec3 pos) {
r_state_push();
// stateless pseudo-random fuckery
int tile = floathash(pos[1] * 3124312) & 1;
float offs = 200 * sin(2*M_PI*remainder(3214.322211333 * floathash(pos[1]), M_E));
int tile = floathash(pos[1] * 311.4312) & 1;
float offs = 600 * sin(2*M_PI*remainder(3214.322211333 * floathash(pos[1]), M_E));
float d = -55+50*sin(pos[1]/25.0);
r_mat_mv_push();
r_mat_mv_translate(pos[0]+offs, pos[1], d);
@ -283,52 +330,136 @@ static void stage1_waterplants_draw(vec3 pos) {
r_state_pop();
}
static bool stage1_fog(Framebuffer *fb) {
r_shader("zbuf_fog");
r_uniform_sampler("depth", r_framebuffer_get_attachment(fb, FRAMEBUFFER_ATTACH_DEPTH));
r_uniform_vec4("fog_color", 0.8, 0.8, 0.8, 1.0);
r_uniform_float("start", 0.0);
r_uniform_float("end", 0.8);
r_uniform_float("exponent", 3.0);
r_uniform_float("sphereness", 0.2);
draw_framebuffer_tex(fb, VIEWPORT_W, VIEWPORT_H);
r_shader_standard();
return true;
static uint stage1_waterplants_pos(Stage3D *s3d, vec3 p, float maxrange) {
vec3 q = {0,0,-300};
vec3 r = {0,150,0};
return linear3dpos(s3d, p, maxrange/2.0, q, r);
}
static void stage1_snow_draw(vec3 pos) {
float o = stage1_bg.snow.opacity;
// float appear_time = 2760;
if(o < 1.0f/256.0f) {
return;
}
float d = fabsf(pos[1] - stage_3d_context.cx[1]);
if(fabsf(d) < 500) {
return;
}
float x = ((d+500)*(d+500))/(5000*5000);
float h0 = floathash(pos[1]+0) / (double)UINT32_MAX;
float h1 = floathash(pos[1]+1) / (double)UINT32_MAX;
float h2 = floathash(pos[1]+2) / (double)UINT32_MAX;
float height = 1 + sawtooth(h0 + global.frames/240.0);
o *= pow(1 - 1.5 * clamp(height - 1, 0, 1), 5) * x;
// o *= min(1, (global.frames - appear_time) / 180.0);
if(o < 1.0f/256.0f) {
return;
}
if(height > 1) {
height = 1;
} else {
height = glm_ease_quad_in(height);
}
if(o > 1) {
o = 1;
}
r_state_push();
r_shader("sprite_default");
r_disable(RCAP_DEPTH_TEST);
r_cull(CULL_BACK);
r_mat_mv_push();
r_mat_mv_translate(pos[0] + 2200 * sawtooth(h1), pos[1] + 10 * sawtooth(h2), 1200 - 1200 * height);
r_mat_mv_rotate(M_PI/2, -1, 0, 0);
r_draw_sprite(&(SpriteParams) {
.sprite = "part/smoothdot",
.color = RGBA(o, o, o, 0),
});
r_mat_mv_pop();
r_state_pop();
}
static uint stage1_snow_pos(Stage3D *s3d, vec3 p, float maxrange) {
vec3 q = {0,0,0};
vec3 r = {0,15,0};
return linear3dpos(s3d, p, maxrange, q, r);
}
void stage1_bg_raise_camera(void) {
stage1_bg.pitch_target = 75;
}
void stage1_bg_enable_snow(void) {
stage1_bg.snow.opacity_target = 1;
}
void stage1_bg_disable_snow(void) {
stage1_bg.snow.opacity_target = 0;
}
static void stage1_draw(void) {
r_mat_proj_perspective(STAGE3D_DEFAULT_FOVY, STAGE3D_DEFAULT_ASPECT, 500, 5000);
r_mat_proj_perspective(STAGE3D_DEFAULT_FOVY, STAGE3D_DEFAULT_ASPECT, 500, 10000);
Stage3DSegment segs[] = {
{ stage1_water_draw, stage1_bg_pos },
{ stage1_waterplants_draw, stage1_smoke_pos },
{ stage1_waterplants_draw, stage1_waterplants_pos },
{ stage1_snow_draw, stage1_snow_pos },
{ stage1_smoke_draw, stage1_smoke_pos },
};
stage3d_draw(&stage_3d_context, 7000, ARRAY_SIZE(segs), segs);
stage3d_draw(&stage_3d_context, 10000, ARRAY_SIZE(segs), segs);
}
static void stage1_update(void) {
stage3d_update(&stage_3d_context);
stage_3d_context.crot[1] = 2 * sin(global.frames/113.0);
stage_3d_context.crot[2] = 1 * sin(global.frames/132.0);
fapproach_asymptotic_p(&stage_3d_context.crot[0], stage1_bg.pitch_target, 0.01, 1e-5);
fapproach_asymptotic_p(&stage1_bg.fog.near, stage1_bg.fog.near_target, 0.001, 1e-5);
fapproach_asymptotic_p(&stage1_bg.fog.far, stage1_bg.fog.far_target, 0.001, 1e-5);
fapproach_p(&stage1_bg.snow.opacity, stage1_bg.snow.opacity_target, 1.0 / 180.0);
}
static void stage1_start(void) {
stage3d_init(&stage_3d_context, 16);
stage_3d_context.crot[0] = 60;
stage_3d_context.cx[2] = 700;
stage_3d_context.cv[1] = 4;
stage3d_init(&stage_3d_context, 64);
FBAttachmentConfig cfg = { 0 };
cfg.attachment = FRAMEBUFFER_ATTACH_COLOR0;
cfg.tex_params.filter.min = TEX_FILTER_LINEAR;
cfg.tex_params.filter.mag = TEX_FILTER_LINEAR;
cfg.tex_params.type = TEX_TYPE_RGB;
cfg.tex_params.type = TEX_TYPE_RGBA;
cfg.tex_params.wrap.s = TEX_WRAP_CLAMP;
cfg.tex_params.wrap.t = TEX_WRAP_CLAMP;
stage1_bg_fbpair.front = stage_add_background_framebuffer("Stage 1 water FB 1", 0.2, 0.5, 1, &cfg);
stage1_bg_fbpair.back = stage_add_background_framebuffer("Stage 1 water FB 2", 0.2, 0.5, 1, &cfg);
stage1_bg.water_fbpair.front = stage_add_background_framebuffer("Stage 1 water FB 1", 0.2, 0.5, 1, &cfg);
stage1_bg.water_fbpair.back = stage_add_background_framebuffer("Stage 1 water FB 2", 0.2, 0.5, 1, &cfg);
stage1_bg.fog.near_target = 0.5;
stage1_bg.fog.far_target = 1.5;
stage1_bg.snow.opacity_target = 0.0;
stage1_bg.pitch_target = 60;
stage1_bg.fog.near = 0.2; // stage1_bg.fog.near_target;
stage1_bg.fog.far = 1.0; // stage1_bg.fog.far_target;
stage1_bg.snow.opacity = stage1_bg.snow.opacity_target;
stage_3d_context.crot[0] = stage1_bg.pitch_target;
stage_3d_context.cx[2] = 700;
stage_3d_context.cv[1] = 8;
}
static void stage1_preload(void) {
@ -340,6 +471,9 @@ static void stage1_preload(void) {
"stage1/waterplants",
"dialog/cirno",
NULL);
preload_resources(RES_TEXTURE, RESF_DEFAULT,
"stage1/horizon",
NULL);
preload_resources(RES_SHADER_PROGRAM, RESF_DEFAULT,
"blur5",
"stage1_water",
@ -358,6 +492,7 @@ static void stage1_preload(void) {
static void stage1_end(void) {
stage3d_shutdown(&stage_3d_context);
memset(&stage1_bg, 0, sizeof(stage1_bg));
}
static void stage1_spellpractice_start(void) {
@ -369,6 +504,16 @@ static void stage1_spellpractice_start(void) {
global.boss = cirno;
stage_start_bgm("stage1boss");
stage1_bg_raise_camera();
stage1_bg_enable_snow();
stage1_bg.fog.near = stage1_bg.fog.near_target;
stage1_bg.fog.far = stage1_bg.fog.far_target;
stage1_bg.snow.opacity = stage1_bg.snow.opacity_target;
stage_3d_context.crot[0] = stage1_bg.pitch_target;
INVOKE_TASK_WHEN(&cirno->events.defeated, common_call_func, stage1_bg_disable_snow);
}
static void stage1_spellpractice_events(void) {

View file

@ -42,6 +42,10 @@ extern struct stage1_spells_s {
extern StageProcs stage1_procs;
extern StageProcs stage1_spell_procs;
void stage1_bg_raise_camera(void);
void stage1_bg_enable_snow(void);
void stage1_bg_disable_snow(void);
#ifdef SPELL_BENCHMARK
extern AttackInfo stage1_spell_benchmark;
#endif

View file

@ -1431,6 +1431,9 @@ TASK(spawn_midboss, NO_ARGS) {
boss_add_attack_task(boss, AT_Move, "Introduction", 2, 0, TASK_INDIRECT(BossAttack, midboss_flee), NULL);
boss_start_attack(boss, boss->attacks);
WAIT(60);
stage1_bg_enable_snow();
}
TASK(tritoss_fairy, { cmplx pos; cmplx velocity; cmplx end_velocity; }) {
@ -1526,6 +1529,9 @@ TASK(stage_timeline, NO_ARGS) {
INVOKE_TASK_DELAYED(900, schedule_swirls);
INVOKE_TASK_DELAYED(1500, burst_fairies_3);
INVOKE_TASK_DELAYED(2200, multiburst_fairies_1);
INVOKE_TASK_DELAYED(2200, common_call_func, stage1_bg_raise_camera);
STAGE_BOOKMARK_DELAYED(2500, pre-midboss);
INVOKE_TASK_DELAYED(2700, spawn_midboss);
while(!global.boss) YIELD;
@ -1597,7 +1603,10 @@ TASK(stage_timeline, NO_ARGS) {
WAIT_EVENT(&global.boss->events.defeated);
stage_unlock_bgm("stage1boss");
WAIT(240);
WAIT(120);
stage1_bg_disable_snow();
WAIT(120);
global.dialog = stage1_dialog_post_boss();
while(dialog_is_active(global.dialog)) {