stage2: update background

This commit is contained in:
Andrei Alexeyev 2021-12-17 14:05:24 +02:00
parent 417471b784
commit 9f19a66328
No known key found for this signature in database
GPG key ID: 72D26128040B9690
52 changed files with 514 additions and 160 deletions

View file

@ -2,5 +2,6 @@
diffuse_map = stage2/branch_diffuse
normal_map = stage2/branch_normal
ambient_map = stage2/branch_ambient
roughness_map = stage2/branch_roughness
ao_map = stage2/branch_ao
roughness = 0.759

Binary file not shown.

Binary file not shown.

View file

@ -1,6 +0,0 @@
diffuse_map = stage2/grass_diffuse
normal_map = stage2/grass_normal
ambient_map = stage2/grass_ambient
roughness_map = stage2/grass_roughness

View file

@ -3,4 +3,5 @@ diffuse_map = stage2/ground_diffuse
normal_map = stage2/ground_normal
ambient_map = stage2/ground_ambient
roughness_map = stage2/ground_roughness
ao_map = stage2/ground_ao

Binary file not shown.

View file

@ -0,0 +1,8 @@
diffuse_map = stage2/lakefloor_diffuse
normal_map = stage2/lakefloor_normal
depth_map = stage2/lakefloor_depth
ambient_color = 0 0 0
roughness = 0.9
depth_scale = 0.04

View file

@ -0,0 +1 @@
anisotropy = 16

View file

@ -0,0 +1,2 @@
anisotropy = 16
linearize = true

View file

@ -0,0 +1 @@
anisotropy = 16

View file

@ -2,5 +2,6 @@
diffuse_map = stage2/leaves_diffuse
normal_map = stage2/leaves_normal
ambient_map = stage2/leaves_ambient
roughness_map = stage2/leaves_roughness
ao_map = stage2/leaves_ao
roughness = 0.777

Binary file not shown.

View file

@ -3,4 +3,5 @@ diffuse_map = stage2/rocks_diffuse
normal_map = stage2/rocks_normal
ambient_map = stage2/rocks_ambient
roughness_map = stage2/rocks_roughness
ao_map = stage2/rocks_ao

Binary file not shown.

View file

@ -0,0 +1,13 @@
#ifndef I_PBR_WATER_H
#define I_PBR_WATER_H
#include "pbr.glslh"
UNIFORM(60) float time;
UNIFORM(61) float water_depth;
UNIFORM(62) float wave_height;
UNIFORM(63) vec2 wave_offset;
UNIFORM(64) float wave_scale;
UNIFORM(65) mat4 inverse_modelview;
#endif

View file

@ -45,6 +45,8 @@ glsl_files = files(
'pbr.vert.glsl',
'pbr_diffuse_alpha_discard.frag.glsl',
'pbr_roughness_alpha_discard.frag.glsl',
'pbr_water.frag.glsl',
'pbr_water.vert.glsl',
'player_death.frag.glsl',
'powersurge_effect.frag.glsl',
'powersurge_feedback.frag.glsl',

View file

@ -0,0 +1,88 @@
#version 330 core
#define PARALLAX_MIN_LAYERS 6
#define PARALLAX_MAX_LAYERS 8
#define STAGE2_OPTIMIZATIONS
#ifdef STAGE2_OPTIMIZATIONS
// hardcoded assumptions in context of stage 2
// these eliminate some uniform branches, so it doesn't win all that much
#define PBR_CONDITIONAL_FEATURES 0
#define PBR_UNCONDITIONAL_FEATURES (PBR_FEATURE_DIFFUSE_MAP | PBR_FEATURE_NORMAL_MAP | PBR_FEATURE_ENVIRONMENT_MAP | PBR_FEATURE_DEPTH_MAP)
#endif
#include "lib/render_context.glslh"
#include "interface/pbr_water.glslh"
#include "lib/util.glslh"
#include "lib/water.glslh"
#include "lib/frag_util.glslh"
#define IOR_TO_F0(ior) ((ior - 1.0) * (ior - 1.0)) / ((ior + 1.0) * (ior + 1.0))
const float IOR_AIR = 1.000;
const float IOR_WATER = 1.333;
const float AIR_TO_WATER = IOR_AIR / IOR_WATER;
const float F0_WATER = IOR_TO_F0(IOR_WATER);
vec3 topLayer(vec3 normal, vec3 pos, vec3 bottom);
vec3 bottomLayer(mat3 tbn, vec2 uv, vec3 pos);
void main(void) {
vec2 uv = rot(pi/2) * (texCoord + vec2(-0*time, 0));
float height = warpedNoise(uv, time);
vec2 dheightduv = wave_height * dFduv(height, uv.xy);
mat3 tbn = mat3(normalize(tangent), normalize(bitangent), normalize(normal));
vec3 surface_normal = normalize(vec3(-dheightduv, 1));
vec3 penetration_vec = refract(normalize(pos), tbn * surface_normal, AIR_TO_WATER);
penetration_vec = transpose(tbn) * penetration_vec;
penetration_vec /= abs(penetration_vec.z);
penetration_vec = tbn * penetration_vec;
vec3 bottom_pos = pos + water_depth * penetration_vec;
vec2 bottom_uv = wave_offset +(inverse_modelview * vec4(bottom_pos, 1.0)).xy;
vec3 bottom = bottomLayer(tbn, bottom_uv, bottom_pos);
vec3 combined = topLayer(tbn * surface_normal, pos, bottom);
PBR_Generic_MaybeTonemap(combined, features_mask);
fragColor = vec4(combined, 1.0);
}
vec3 topLayer(vec3 normal, vec3 pos, vec3 bottom) {
PBRParams p;
p.fragPos = pos;
p.inv_camera_transform = inv_camera_transform;
p.mat.roughness = 0.1;
p.mat.metallic = 0;
p.mat.normal = normal;
p.mat.ambient_occlusion = 1;
PBRState pbr = PBR(p);
pbr.F0 = vec3(F0_WATER);
vec3 color = PBR_PointLights(pbr, light_count, light_positions, light_colors);
color += PBR_Generic_EnvironmentLight(pbr, ibl_brdf_lut, environment_map, features_mask);
return mix(bottom, color, pbr.fresnelNV);
}
vec3 bottomLayer(mat3 tbn, vec2 uv, vec3 pos) {
PBRParams p;
p.fragPos = pos;
p.inv_camera_transform = inv_camera_transform;
PBR_Interface_LoadMaterial(p.mat, uv, pos, tbn, features_mask);
PBRState pbr = PBR(p);
vec3 color = p.mat.ambient;
color += PBR_PointLights(pbr, light_count, light_positions, light_colors);
color += PBR_Generic_EnvironmentLight(pbr, ibl_brdf_lut, environment_map, features_mask);
return color;
}

View file

@ -0,0 +1,2 @@
objects = pbr_water.vert pbr_water.frag

View file

@ -0,0 +1,18 @@
#version 330
#include "lib/render_context.glslh"
#include "interface/pbr_water.glslh"
#include "lib/util.glslh"
void main(void) {
pos = (r_modelViewMatrix * vec4(position,1.0)).xyz;
gl_Position = r_projectionMatrix * vec4(pos, 1.0);
mat3 mv3 = mat3(r_modelViewMatrix);
normal = normalize(mv3 * normalIn);
tangent = normalize(mv3 * tangentIn.xyz);
bitangent = normalize(mv3 * cross(normalIn.xyz, tangentIn.xyz) * tangentIn.w);
mat2 trans = wave_scale * rot(-3*pi/4);
texCoord = trans * flip_native_to_bottomleft(texCoordRawIn - wave_offset);
}

View file

@ -16,46 +16,61 @@
#include "common_tasks.h"
#include "util/glm.h"
TASK(animate_hina_mode) {
TASK(animate_color_shift) {
Stage2DrawData *draw_data = stage2_get_draw_data();
int dur = 10000;
int dur = 12000;
Color fog_color_start = draw_data->fog.color;
Color fog_color_final = *RGBA(0.1,0.1,1.0,1.0);
Color fog_color_final = *RGBA(0.1, 0.1, 1.0, 1.0);
for(int i = 0; i < dur; i++) {
YIELD;
draw_data->hina_lights = glm_ease_linear(i/(real)dur);
draw_data->fog.color = *color_lerp(&fog_color_start, &fog_color_final, draw_data->hina_lights);
for(int i = 0; i < dur; i++, YIELD) {
draw_data->fog.color = *color_lerp(
&fog_color_start,
&fog_color_final,
i/(float)dur
);
}
}
void stage2_bg_engage_hina_mode(void) {
INVOKE_TASK(animate_hina_mode);
void stage2_bg_begin_color_shift(void) {
INVOKE_TASK(animate_color_shift);
}
void stage2_bg_enable_hina_lights(void) {
Stage2DrawData *draw_data = stage2_get_draw_data();
INVOKE_TASK(common_easing_animate,
.value = &draw_data->hina_lights,
.to = 1.0f,
.duration = 60,
.ease = glm_ease_sine_in,
);
}
#include "camcontrol.h"
TASK(animate_bg_fullstage) {
Camera3D *cam = &stage_3d_context.cam;
cam->pos[2] = 8;
cam->pos[0] = 10;
cam->rot.v[0] = 50;
cam->rot.v[0] = 70;
cam->rot.v[2] = -90;
Stage2DrawData *draw_data = stage2_get_draw_data();
draw_data->fog.color = *RGBA(0.5, 0.6, 0.9, 1.0);
draw_data->fog.color = *RGBA(0.45, 0.5, 0.5, 1);
draw_data->fog.end = 1.0;
INVOKE_TASK(common_easing_animate_vec4,
&draw_data->fog.color.rgba, { 0.04, 0.06, 0.09, 1 }, 1600, glm_ease_quad_out);
INVOKE_TASK_DELAYED(155, common_easing_animate,
&draw_data->fog.end, 3.8, 2000, glm_ease_quad_out);
real dur = 600;
glm_ease_t func = glm_ease_quad_inout;
INVOKE_TASK(common_easing_animate,&cam->rot.v[0], 40, dur, glm_ease_quad_out);
INVOKE_TASK(common_easing_animate,&cam->rot.v[2], -2.5f, dur, glm_ease_quad_out);
INVOKE_TASK(common_easing_animate,&cam->pos[0], 0, dur, func);
INVOKE_TASK(common_easing_animate,&cam->vel[1], 0.05f, dur, func);
INVOKE_TASK(common_easing_animate, &cam->rot.v[0], 40, dur, glm_ease_quad_out);
INVOKE_TASK(common_easing_animate, &cam->rot.v[2], -2.5f, dur, glm_ease_quad_out);
INVOKE_TASK(common_easing_animate, &cam->pos[0], 0, dur, func);
INVOKE_TASK(common_easing_animate, &cam->rot.v[0], 50, dur, glm_ease_quad_out);
INVOKE_TASK(common_easing_animate, &cam->rot.v[2], -6, dur, glm_ease_quad_out);
INVOKE_TASK(common_easing_animate, &cam->pos[0], -0.38, dur, func);
INVOKE_TASK(common_easing_animate, &cam->pos[2], 8, dur, func);
INVOKE_TASK(common_easing_animate, &cam->vel[1], 0.05f, dur, func);
for(;;) {
@ -72,14 +87,15 @@ TASK(animate_bg_spellpractice) {
Camera3D *cam = &stage_3d_context.cam;
cam->pos[2] = 8;
cam->pos[0] = 0;
cam->rot.v[0] = 40;
cam->rot.v[2] = -2.5f;
cam->pos[0] = -0.38;
cam->rot.v[0] = 50;
cam->rot.v[2] = -6;
cam->vel[1] = 0.05f;
Stage2DrawData *draw_data = stage2_get_draw_data();
draw_data->fog.color = *RGBA(0.1, 0.1, 1, 1.0);
draw_data->hina_lights = 0.0;
draw_data->hina_lights = 1.0;
draw_data->fog.end = 3.8;
for(;;) {
YIELD;

View file

@ -12,4 +12,5 @@
void stage2_bg_init_fullstage(void);
void stage2_bg_init_spellpractice(void);
void stage2_bg_engage_hina_mode(void);
void stage2_bg_begin_color_shift(void);
void stage2_bg_enable_hina_lights(void);

View file

@ -10,9 +10,10 @@
#include "draw.h"
#include "renderer/api.h"
#include "stageutils.h"
#include "global.h"
#include "renderer/api.h"
#include "resource/model.h"
#include "stageutils.h"
#include "util/glm.h"
static Stage2DrawData *stage2_draw_data;
@ -22,55 +23,152 @@ Stage2DrawData *stage2_get_draw_data(void) {
}
#define STAGE2_MAX_LIGHTS 4
#define NUM_HINA_LIGHTS 3
#define TESTLIGHTS 0
#if TESTLIGHTS
#define NUM_TESTLIGHTS 5
#define TESTLIGHT_STRENGTH 100
#define TESTLIGHT_CAMDIST 20
#define TESTLIGHT_CENTERDIST 3
#else
#define NUM_TESTLIGHTS 0
#endif
#define WATER_SIZE 25
#define WATER_ORIGIN { 15, -WATER_SIZE, -0.5 }
#define BRANCH_DIST 2
#if TESTLIGHTS
static void testlights(Camera3D *cam, uint nlights, PointLight3D lights[nlights]) {
mat4 camera_trans;
camera3d_apply_inverse_transforms(cam, camera_trans);
vec3 forward = { 0, 0, -1 };
vec3 right = { 1, 0, 0 };
vec3 up = { 0, 1, 0 };
vec3 X = { TESTLIGHT_CENTERDIST, 0, 0 };
vec3 Y = { 0, TESTLIGHT_CENTERDIST, 0 };
glm_vec3_rotate_m4(camera_trans, forward, forward);
glm_vec3_rotate_m4(camera_trans, right, right);
glm_vec3_rotate_m4(camera_trans, up, up);
vec3 orig;
glm_vec3_copy(cam->pos, orig);
glm_vec3_muladds(forward, TESTLIGHT_CAMDIST, orig);
cmplxf r = cdir(global.frames * DEG2RAD);
cmplxf p = cdir(M_TAU / nlights);
for(int i = 0; i < nlights; ++i) {
PointLight3D *l = lights + i;
glm_vec3_scale(HSL(i / (float)nlights, 1, 0.5)->rgb, TESTLIGHT_STRENGTH, l->radiance);
glm_vec3_copy(orig, l->pos);
glm_vec3_muladds(X, crealf(r), l->pos);
glm_vec3_muladds(Y, cimagf(r), l->pos);
r *= p;
}
}
#endif
static uint stage2_hina_lights(Camera3D *cam, uint num_lights, PointLight3D lights[num_lights]) {
Stage2DrawData *draw_data = stage2_get_draw_data();
float intensity = draw_data->hina_lights;
if(!global.boss || intensity <= 0) {
return 0;
}
vec3 r;
camera3d_unprojected_ray(cam, global.boss->pos, r);
float t = (0.1f - cam->pos[2]) / r[2];
glm_vec3_scale(r, t, r);
vec3 hina_center;
glm_vec3_add(cam->pos, r, hina_center);
vec3 radiance = { 1, 0, 30 };
glm_vec3_scale(radiance, intensity, radiance);
for(int i = 0; i < num_lights; i++) {
PointLight3D *l = lights + i;
float angle = M_TAU / num_lights * i + 0.75f * global.frames/(float)FPS;
vec3 offset = { cosf(angle), sinf(angle) };
glm_vec3_scale(offset, 4.0f + sinf(3.0f * angle), offset);
glm_vec3_add(hina_center, offset, l->pos);
glm_vec3_copy(radiance, l->radiance);
}
return num_lights;
}
static void stage2_bg_setup_pbr_lighting(Camera3D *cam, int max_lights) {
// FIXME: Instead of calling this for each segment, maybe set up the lighting once for the whole scene?
PointLight3D lights[STAGE2_MAX_LIGHTS] = {
PointLight3D lights[STAGE2_MAX_LIGHTS + NUM_TESTLIGHTS] = {
{ { 100, cam->pos[1] - 100, 100 }, { 50000, 50000, 50000 } },
{ { 0, 0, 0 }, { 1, 0, 30 } },
{ { 0, 0, 0 }, { 1, 0, 30 } },
{ { 0, 0, 0 }, { 1, 0, 30 } },
};
Stage2DrawData *draw_data = stage2_get_draw_data();
uint first_hina_light = 1;
if(global.boss && draw_data->hina_lights > 0) {
vec3 r;
camera3d_unprojected_ray(cam, global.boss->pos, r);
real t = (0.1-cam->pos[2])/r[2];
glm_vec3_scale(r, t, r);
vec3 hina_center;
glm_vec3_add(cam->pos, r, hina_center);
int hina_light_count = 3;
for(int i = 0; i < hina_light_count; i++) {
real angle = 2 * M_PI / hina_light_count * i + global.frames/(real)FPS;
vec3 offset = {cos(angle), sin(angle)};
glm_vec3_scale(offset, 4+sin(3*angle), offset);
glm_vec3_add(hina_center, offset, lights[1+i].pos);
glm_vec3_scale(lights[1+i].radiance, draw_data->hina_lights, lights[1+i].radiance);
}
} else {
max_lights = 1;
if(max_lights >= first_hina_light + NUM_HINA_LIGHTS) {
max_lights += stage2_hina_lights(cam, NUM_HINA_LIGHTS, lights + first_hina_light);
max_lights -= NUM_HINA_LIGHTS;
}
#if 0
testlights(cam, NUM_TESTLIGHTS, lights + max_lights);
float f = 0.1f + 0.9f * (0.5f + 0.5f * sinf(global.frames / 30.0f));
for(int i = max_lights; i < max_lights + NUM_TESTLIGHTS; ++i) {
PointLight3D *l = lights + i;
glm_vec3_scale(l->radiance, f, l->radiance);
}
max_lights += NUM_TESTLIGHTS;
#endif
camera3d_set_point_light_uniforms(cam, imin(max_lights, ARRAY_SIZE(lights)), lights);
}
static void stage2_bg_setup_pbr_env(Camera3D *cam, int max_lights, PBREnvironment *env) {
stage2_bg_setup_pbr_lighting(cam, max_lights);
glm_vec3_broadcast(0.5f, env->ambient_color);
camera3d_apply_inverse_transforms(cam, env->cam_inverse_transform);
env->environment_map = stage2_draw_data->envmap;
env->disable_tonemap = true;
}
static void stage2_branch_mv_transform(vec3 pos) {
float f1 = sinf(12123.0f * pos[1] * pos[1]);
float f2 = cosf(2340.0f * f1 * f1);
float f3 = cosf(2469.0f * f2 * f2);
uint64_t seed = stage2_draw_data->branch_rng_seed ^ float_to_bits(pos[1]);
r_mat_mv_translate(pos[0] - f3 * f3, pos[1] + f2, pos[2] + 0.5f * f1);
r_mat_mv_rotate(-M_PI/2.0f + 0.4f * f1, 0, 0.05f * f3, 1);
#if 0
RandomState rng;
rng_init(&rng, seed);
#define RAND() vrng_f32s(rng_next_p(&rng))
#else
#define RAND() vrng_f32s((rng_val_t) { splitmix64(&seed) })
#endif
float r0 = RAND();
float r1 = RAND();
float r2 = RAND();
float r3 = RAND();
float r4 = RAND();
float r5 = RAND();
#undef RAND
pos[0] += 0.5f * r0 - 0.8f;
pos[1] += 0.4f * BRANCH_DIST * r1;
pos[2] += 0.6f * r2 - 0.25f;
r_mat_mv_translate_v(pos);
r_mat_mv_rotate(r3 * M_PI/16, 1, 0, 0);
r_mat_mv_rotate(r4 * M_PI/8 , 0, 0, 1);
r_mat_mv_rotate(r5 * M_PI/16, 0, 1, 0);
}
static void stage2_bg_branch_draw(vec3 pos) {
@ -96,7 +194,7 @@ static void stage2_bg_leaves_draw(vec3 pos) {
r_mat_mv_push();
stage2_branch_mv_transform(pos);
r_shader("pbr_roughness_alpha_discard");
r_shader("pbr_diffuse_alpha_discard");
PBREnvironment env = { 0 };
stage2_bg_setup_pbr_env(&stage_3d_context.cam, 1, &env);
@ -107,67 +205,35 @@ static void stage2_bg_leaves_draw(vec3 pos) {
r_state_pop();
}
static void stage2_bg_grass_draw(vec3 pos) {
r_state_push();
float f1 = sinf(123.0f * pos[1] * pos[1]);
float f2 = cosf(234350.0f * f1 * f1);
float f3 = cosf(24269.0f * f2 * f2);
r_mat_mv_push();
r_mat_mv_translate(pos[0]-f3*f3, pos[1]+f2, pos[2]);
r_mat_mv_rotate(-M_PI/2 * 1.2, 1, 0, 0);
r_mat_mv_scale(2, 2, 2);
ShaderProgram *sprite_shader = res_shader("sprite_pbr");
r_shader_ptr(sprite_shader);
PBREnvironment env = { 0 };
stage2_bg_setup_pbr_env(&stage_3d_context.cam, STAGE2_MAX_LIGHTS, &env);
r_disable(RCAP_CULL_FACE);
Sprite grass = { 0 };
grass.tex = res_texture("stage2/grass_diffuse");
grass.extent.as_cmplx = 1 + I;
grass.tex_area.extent.as_cmplx = 1 + I;
SpriteParams sp = { 0 };
sp.sprite_ptr = &grass;
sp.color = RGB(1, 1, 1);
// ambient color and metallicity
sp.shader_params = &(ShaderCustomParams) {{ 0.4, 0.4, 0.4, 0 }};
sp.shader_ptr = sprite_shader;
sp.aux_textures[0] = res_texture("stage2/grass_ambient");
sp.aux_textures[1] = res_texture("stage2/grass_normal");
sp.aux_textures[2] = res_texture("stage2/grass_roughness");
int n = 3;
for(int i = 0; i < n; i++) {
r_mat_mv_push();
r_mat_mv_rotate(M_PI*(i-n/2)/n*0.6,0,1,0);
r_mat_mv_translate((i-n/2)*0.2*f1,0,0);
r_draw_sprite(&sp);
r_mat_mv_pop();
}
r_mat_mv_pop();
r_state_pop();
}
static void stage2_bg_ground_draw(vec3 pos) {
r_state_push();
r_mat_mv_push();
r_mat_mv_translate(pos[0], pos[1], pos[2]);
r_mat_mv_translate_v(pos);
r_blend(BLEND_NONE);
r_shader("pbr");
PBREnvironment env = { 0 };
stage2_bg_setup_pbr_env(&stage_3d_context.cam, STAGE2_MAX_LIGHTS, &env);
pbr_draw_model(&stage2_draw_data->models.ground, &env);
r_mat_mv_pop();
r_state_pop();
}
static void stage2_bg_ground_rocks_draw(vec3 pos) {
r_state_push();
r_mat_mv_push();
r_mat_mv_translate_v(pos);
r_blend(BLEND_NONE);
r_shader("pbr");
PBREnvironment env = { 0 };
stage2_bg_setup_pbr_env(&stage_3d_context.cam, STAGE2_MAX_LIGHTS, &env);
pbr_draw_model(&stage2_draw_data->models.rocks, &env);
pbr_draw_model(&stage2_draw_data->models.ground, &env);
r_mat_mv_pop();
r_state_pop();
@ -177,12 +243,13 @@ static void stage2_bg_ground_grass_draw(vec3 pos) {
r_state_push();
r_mat_mv_push();
r_mat_mv_translate(pos[0], pos[1], pos[2]);
r_mat_mv_translate_v(pos);
r_shader("pbr_roughness_alpha_discard");
r_blend(BLEND_PREMUL_ALPHA);
r_disable(RCAP_CULL_FACE);
r_shader("pbr_diffuse_alpha_discard");
PBREnvironment env = { 0 };
stage2_bg_setup_pbr_env(&stage_3d_context.cam, STAGE2_MAX_LIGHTS, &env);
glm_vec3_broadcast(0.4f, env.ambient_color);
pbr_draw_model(&stage2_draw_data->models.grass, &env);
@ -190,23 +257,31 @@ static void stage2_bg_ground_grass_draw(vec3 pos) {
r_state_pop();
}
#define STAGE2_WATER_SIZE 25
static void stage2_bg_water_draw(vec3 pos) {
r_state_push();
r_shader("stage1_water");
r_uniform_sampler("tex", "stage2/water_floor");
r_shader("pbr_water");
r_uniform_float("time", 0.2 * global.frames / (float)FPS);
r_uniform_float("wave_height", 0.06);
r_uniform_float("wave_scale", 16);
r_uniform_vec2("wave_offset", pos[0]/WATER_SIZE, pos[1]/WATER_SIZE);
r_uniform_float("water_depth", 5.0);
PBREnvironment env = { 0 };
stage2_bg_setup_pbr_env(&stage_3d_context.cam, STAGE2_MAX_LIGHTS, &env);
r_mat_mv_push();
static const Color water_color = { 0, 0.08, 0.08, 1 };
r_uniform_vec4_rgba("water_color", &water_color);
r_uniform_vec2("wave_offset", pos[0]/STAGE2_WATER_SIZE,pos[1]/STAGE2_WATER_SIZE);
r_mat_mv_translate(pos[0], pos[1], pos[2]);
r_mat_mv_scale(-STAGE2_WATER_SIZE,STAGE2_WATER_SIZE,1);
r_draw_quad();
r_mat_mv_scale(-WATER_SIZE, WATER_SIZE, 1);
mat4 imv;
glm_mat4_inv_fast(*r_mat_mv_current_ptr(), imv);
r_uniform_mat4("inverse_modelview", imv);
r_mat_tex_push();
r_mat_tex_translate(pos[0], pos[1], 0);
pbr_draw_model(&stage2_draw_data->models.water, &env);
r_mat_tex_pop();
r_mat_mv_pop();
r_state_pop();
@ -216,58 +291,164 @@ static uint stage2_bg_pos(Stage3D *s3d, vec3 cam, float maxrange) {
vec3 orig = {0, 0, 0};
vec3 step = {0, 5, 0};
return stage3d_pos_ray_nearfirst_nsteps(s3d, cam, orig, step, 4, 0);
return stage3d_pos_ray_nearfirst_nsteps(s3d, cam, orig, step, 6, 0);
}
static uint stage2_bg_water_pos(Stage3D *s3d, vec3 cam, float maxrange) {
vec3 orig = {7, 8, -1};
vec3 step = {0, STAGE2_WATER_SIZE, 0};
vec3 orig = WATER_ORIGIN;
vec3 step = {0, WATER_SIZE, 0};
return stage3d_pos_ray_nearfirst_nsteps(s3d, cam, orig, step, 1, 0);
return stage3d_pos_ray_nearfirst_nsteps(s3d, cam, orig, step, 10, 10);
}
static uint stage2_bg_water_start_pos(Stage3D *s3d, vec3 cam, float maxrange) {
vec3 pos = {7+STAGE2_WATER_SIZE, 6, -1};
vec3 o = WATER_ORIGIN;
return stage3d_pos_single(s3d, cam, pos, maxrange*2);
float r = maxrange * 20;
int c = 0;
for(int x = 1; x <= 2; ++x) {
for(int y = 0; y <= 3; ++y) {
vec3 p = { o[0]+x*WATER_SIZE, o[1]+y*WATER_SIZE, o[2] };
c += stage3d_pos_single(s3d, cam, p, r);
}
}
return c;
}
static uint stage2_bg_branch_pos(Stage3D *s3d, vec3 cam, float maxrange) {
vec3 orig = {-1, 0, 3.5};
vec3 step = {0, 2, 0};
vec3 step = {0, BRANCH_DIST, 0};
return stage3d_pos_ray_nearfirst_nsteps(s3d, cam, orig, step, 5, 0);
}
static uint stage2_bg_grass_pos(Stage3D *s3d, vec3 cam, float maxrange) {
vec3 orig = {-2.6, 0, 0.7};
vec3 step = {0, 0.9, 0};
return stage3d_pos_ray_nearfirst(s3d, cam, orig, step, maxrange, 0);
return stage3d_pos_ray_nearfirst_nsteps(s3d, cam, orig, step, 8, 0);
}
static bool stage2_fog(Framebuffer *fb) {
r_shader("zbuf_fog");
Stage2DrawData *dd = stage2_get_draw_data();
r_shader("zbuf_fog_tonemap");
r_uniform_sampler("depth", r_framebuffer_get_attachment(fb, FRAMEBUFFER_ATTACH_DEPTH));
r_uniform_vec4_rgba("fog_color", &stage2_get_draw_data()->fog.color);
r_uniform_float("start", 0.2);
r_uniform_float("end", 3.8);
r_uniform_float("exponent", 3.0);
r_uniform_vec4_rgba("fog_color", &dd->fog.color);
r_uniform_float("start", 0.0);
r_uniform_float("end", dd->fog.end);
r_uniform_float("exponent", 24.0);
r_uniform_float("curvature", 0);
vec3 exp = { 0.9f, 0.95f, 1.0f };
glm_vec3_scale(exp, 0.7, exp);
r_uniform_vec3_vec("exposure", exp);
draw_framebuffer_tex(fb, VIEWPORT_W, VIEWPORT_H);
r_shader_standard();
return true;
}
static uint stage2_testlights_pos(Stage3D *s3d, vec3 cam, float maxrange) {
return stage3d_pos_single(s3d, cam, cam, maxrange);
}
#if TESTLIGHTS
static void stage3d_testlights_draw(vec3 pos) {
r_state_push();
r_mat_mv_push();
r_shader_standard_notex();
r_blend(BLEND_PREMUL_ALPHA);
r_disable(RCAP_CULL_FACE);
Camera3D *cam = &stage_3d_context.cam;
PointLight3D lights[NUM_TESTLIGHTS];
testlights(cam, ARRAY_SIZE(lights), lights);
Model *mdl = res_model("cube");
float scale = 0.05;
for(int i = 0; i < ARRAY_SIZE(lights); ++i) {
PointLight3D *l = lights + i;
r_mat_mv_push();
r_mat_mv_translate_v(l->pos);
r_mat_mv_scale(scale, scale, scale);
Color c = { 0, 0, 0, 1 };
glm_vec3_divs(l->radiance, TESTLIGHT_STRENGTH, c.rgb);
color_mul_scalar(&c, 0.5);
r_color(&c);
r_draw_model_ptr(mdl, 0, 0);
r_mat_mv_pop();
}
r_mat_mv_pop();
r_state_pop();
}
#endif
static void stage3d_hinalights_draw(vec3 pos) {
r_state_push();
r_mat_mv_push();
r_shader_standard_notex();
r_blend(BLEND_PREMUL_ALPHA);
r_disable(RCAP_DEPTH_WRITE);
r_disable(RCAP_CULL_FACE);
uint instances = 64;
const Model *quad = r_model_get_quad();
Sprite *spr = res_sprite("part/stain");
r_shader("fireparticles");
r_uniform_sampler("sprite_tex", spr->tex);
r_uniform_vec3("color_base", 1, 0, 0);
r_uniform_vec3("color_nstate", 0, 0, 1);
r_uniform_vec3("color_nstate2", 0, 0.2, 1);
r_uniform_vec4("tint", 1, 1, 1, 0);
r_uniform_vec4("sprite_tex_region",
spr->tex_area.x,
spr->tex_area.y,
spr->tex_area.w,
spr->tex_area.h
);
r_uniform_float("time", global.frames / 120.0f);
Camera3D *cam = &stage_3d_context.cam;
PointLight3D lights[NUM_HINA_LIGHTS];
uint nlights = stage2_hina_lights(cam, ARRAY_SIZE(lights), lights);
uint32_t seed = 0xabcdef69;
for(int i = 0; i < nlights; ++i) {
float s0 = splitmix32(&seed) / (double)UINT32_MAX;
float s1 = splitmix32(&seed) / (double)UINT32_MAX;
r_uniform_vec2("seed", s0, s1);
PointLight3D *l = lights + i;
r_mat_mv_push();
r_mat_mv_translate_v(l->pos);
mat4 *mv = r_mat_mv_current_ptr();
glm_mul(*mv, stage2_draw_data->hina_fire_emitter_transform, *mv);
r_draw_model_ptr(quad, instances, 0);
r_mat_mv_pop();
}
r_mat_mv_pop();
r_state_pop();
}
void stage2_draw(void) {
Stage3DSegment segs[] = {
{ stage2_bg_branch_draw, stage2_bg_branch_pos },
{ stage2_bg_ground_rocks_draw, stage2_bg_pos},
{ stage2_bg_ground_draw, stage2_bg_pos},
{ stage2_bg_water_draw, stage2_bg_water_pos},
{ stage2_bg_water_draw, stage2_bg_water_start_pos},
{ stage2_bg_leaves_draw, stage2_bg_branch_pos },
{ stage2_bg_grass_draw, stage2_bg_grass_pos },
{ stage2_bg_ground_grass_draw, stage2_bg_pos },
{ stage2_bg_ground_grass_draw, stage2_bg_pos},
{ stage3d_hinalights_draw, stage2_testlights_pos },
#if TESTLIGHTS
{ stage3d_testlights_draw, stage2_testlights_pos },
#endif
};
stage3d_draw(&stage_3d_context, 20, ARRAY_SIZE(segs), segs);
@ -280,10 +461,22 @@ void stage2_drawsys_init(void) {
stage2_draw_data = calloc(1, sizeof(*stage2_draw_data));
pbr_load_model(&stage2_draw_data->models.branch, "stage2/branch", "stage2/branch");
pbr_load_model(&stage2_draw_data->models.grass, "stage2/grass", "stage2/grass");
pbr_load_model(&stage2_draw_data->models.grass, "stage2/grass", "stage2/ground");
pbr_load_model(&stage2_draw_data->models.ground, "stage2/ground", "stage2/ground");
pbr_load_model(&stage2_draw_data->models.leaves, "stage2/leaves", "stage2/leaves");
pbr_load_model(&stage2_draw_data->models.rocks, "stage2/rocks", "stage2/rocks");
stage2_draw_data->models.water.mdl = (Model*)r_model_get_quad();
stage2_draw_data->models.water.mat = res_material("stage2/lakefloor");
mat4 *m = &stage2_draw_data->hina_fire_emitter_transform;
glm_mat4_identity(*m);
glm_rotate_x(*m, -M_PI/2, *m);
float s = 0.6f;
glm_scale_to(*m, (vec3) { 0.5f * s, s, s }, *m);
stage2_draw_data->envmap = res_texture("stage2/envmap");
stage2_draw_data->branch_rng_seed = makeseed();
}
void stage2_drawsys_shutdown(void) {

View file

@ -15,17 +15,24 @@
typedef struct Stage2DrawData {
struct {
Color color;
float end;
} fog;
struct {
PBRModel branch;
PBRModel grass;
PBRModel ground;
PBRModel water;
PBRModel leaves;
PBRModel rocks;
} models;
real hina_lights;
Texture *envmap;
float hina_lights;
mat4 hina_fire_emitter_transform;
uint64_t branch_rng_seed;
} Stage2DrawData;
Stage2DrawData *stage2_get_draw_data(void)

View file

@ -78,14 +78,15 @@ static void stage2_preload(void) {
"part/blast_huge_rays",
NULL);
preload_resources(RES_TEXTURE, RESF_DEFAULT,
"stage2/water_floor",
"ibl_brdf_lut",
"stage2/envmap",
"stage2/spellbg1",
"stage2/spellbg2",
NULL);
preload_resources(RES_MATERIAL, RESF_DEFAULT,
"stage2/branch",
"stage2/grass",
"stage2/ground",
"stage2/lakefloor",
"stage2/leaves",
"stage2/rocks",
NULL);
@ -97,11 +98,11 @@ static void stage2_preload(void) {
"stage2/rocks",
NULL);
preload_resources(RES_SHADER_PROGRAM, RESF_DEFAULT,
"bloom",
"fireparticles",
"pbr",
"pbr_roughness_alpha_discard",
"stage1_water",
"zbuf_fog",
"pbr_diffuse_alpha_discard",
"pbr_water",
"zbuf_fog_tonemap",
NULL);
preload_resources(RES_ANIM, RESF_DEFAULT,
"boss/wriggle",

View file

@ -613,6 +613,8 @@ TASK(boss_appear, { BoxedBoss boss; }) {
aniplayer_queue(&boss->ani, "guruguru", 2);
aniplayer_queue(&boss->ani, "main", 0);
stage2_bg_enable_hina_lights();
}
TASK(spawn_boss) {
@ -798,6 +800,7 @@ DEFINE_EXTERN_TASK(stage2_timeline) {
WAIT(filler_time - midboss_time);
STAGE_BOOKMARK(post-midboss-filler);
stage2_bg_begin_color_shift();
INVOKE_TASK(aimshot_fairies_red);
@ -840,7 +843,7 @@ DEFINE_EXTERN_TASK(stage2_timeline) {
}
WAIT(860);
stage2_bg_engage_hina_mode();
// stage2_bg_engage_hina_mode();
WAIT(300);
stage_clear_hazards(CLEAR_HAZARDS_ALL);
INVOKE_TASK(spawn_boss);