taisei/src/stages/stage3/draw.c
2024-05-17 14:11:48 +02:00

176 lines
4.7 KiB
C

/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "draw.h"
#include "stageutils.h"
#include "global.h"
#include "util/glm.h"
#include "util/graphics.h"
static Stage3DrawData *stage3_draw_data;
Stage3DrawData *stage3_get_draw_data(void) {
return NOT_NULL(stage3_draw_data);
}
static uint stage3_bg_pos(Stage3D *s3d, vec3 cam, float maxrange) {
vec3 orig = { 0, 0, 0, };
vec3 step = { 0, 20, 10 };
return stage3d_pos_ray_nearfirst_nsteps(s3d, cam, orig, step, 2, 0);
}
static void stage3_bg_setup_pbr_lighting(Camera3D *cam) {
PointLight3D lights[2] = {
{ { 0, 0, 0 }, { 10, 10, 10 } },
};
PointLight3D *boss_light = &lights[1];
uint nlights = 1;
if(stage3_draw_data->boss_light_alpha > 0) {
glm_vec3_scale(
stage3_draw_data->boss_light.radiance,
stage3_draw_data->boss_light_alpha,
boss_light->radiance
);
glm_vec3_copy(stage3_draw_data->boss_light.pos, boss_light->pos);
nlights++;
}
vec3 r;
camera3d_unprojected_ray(cam, global.plr.pos, r);
glm_vec3_scale(r, 5, r);
glm_vec3_add(cam->pos, r, lights[0].pos);
camera3d_set_point_light_uniforms(cam, nlights, lights);
}
static void stage3_bg_setup_pbr_env(Camera3D *cam, PBREnvironment *env) {
Stage3DrawData *dd = stage3_get_draw_data();
stage3_bg_setup_pbr_lighting(cam);
glm_vec3_copy(dd->ambient_color, env->ambient_color);
glm_vec3_copy(dd->environment_color, env->environment_color);
camera3d_apply_inverse_transforms(cam, env->cam_inverse_transform);
env->environment_map = stage3_draw_data->envmap;
env->disable_tonemap = true;
}
static void stage3_bg_ground_draw(vec3 pos) {
r_state_push();
r_mat_mv_push();
r_mat_mv_translate_v(pos);
r_shader("pbr");
PBREnvironment env = { 0 };
stage3_bg_setup_pbr_env(&stage_3d_context.cam, &env);
pbr_draw_model(&stage3_draw_data->models.trees, &env);
pbr_draw_model(&stage3_draw_data->models.rocks, &env);
pbr_draw_model(&stage3_draw_data->models.ground, &env);
r_mat_mv_pop();
r_state_pop();
}
static void stage3_bg_leaves_draw(vec3 pos) {
r_state_push();
r_mat_mv_push();
r_mat_mv_translate_v(pos);
r_mat_mv_translate(0, 0, -0.0002);
r_shader("pbr_roughness_alpha_discard");
PBREnvironment env = { 0 };
stage3_bg_setup_pbr_env(&stage_3d_context.cam, &env);
pbr_draw_model(&stage3_draw_data->models.leaves, &env);
r_mat_mv_pop();
r_state_pop();
}
void stage3_drawsys_init(void) {
stage3d_init(&stage_3d_context, 16);
stage_3d_context.cam.pos[1] = -16;
stage_3d_context.cam.rot.v[0] = 80;
stage_3d_context.cam.vel[1] = 0.1;
stage_3d_context.cam.vel[2] = 0.05;
stage3_draw_data = ALLOC(typeof(*stage3_draw_data));
pbr_load_model(&stage3_draw_data->models.ground, "stage3/ground", "stage3/ground"); pbr_load_model(&stage3_draw_data->models.leaves, "stage3/leaves", "stage3/leaves");
pbr_load_model(&stage3_draw_data->models.rocks, "stage3/rocks", "stage3/rocks");
pbr_load_model(&stage3_draw_data->models.trees, "stage3/trees", "stage3/trees");
stage3_draw_data->envmap = res_texture("stage3/envmap");
}
void stage3_drawsys_shutdown(void) {
stage3d_shutdown(&stage_3d_context);
mem_free(stage3_draw_data);
}
static bool stage3_fog(Framebuffer *fb) {
Stage3DrawData *dd = stage3_get_draw_data();
r_shader("zbuf_fog_tonemap");
r_uniform_sampler("depth", r_framebuffer_get_attachment(fb, FRAMEBUFFER_ATTACH_DEPTH));
r_uniform_vec4_vec("fog_color", dd->fog_color);
r_uniform_float("start", 0.9);
r_uniform_float("end", 2);
r_uniform_float("exponent", 1);
r_uniform_float("curvature", 0);
float e = 1;
r_uniform_vec3("exposure", e, e, e);
draw_framebuffer_tex(fb, VIEWPORT_W, VIEWPORT_H);
r_shader_standard();
return true;
}
static bool stage3_glitch(Framebuffer *fb) {
float strength;
if(global.boss && global.boss->current && ATTACK_IS_SPELL(global.boss->current->type) && !strcmp(global.boss->name, "Scuttle")) {
strength = 0.05f * max(0, (global.frames - global.boss->current->starttime) / (float)global.boss->current->timeout);
} else {
strength = 0.0;
}
if(strength > 0) {
r_shader("glitch");
r_uniform_float("strength", strength);
r_uniform_float("frames", global.frames + 15 * rng_sreal());
} else {
return false;
}
draw_framebuffer_tex(fb, VIEWPORT_W, VIEWPORT_H);
r_shader_standard();
return true;
}
void stage3_draw(void) {
Stage3DSegment segments[] = {
{ stage3_bg_leaves_draw, stage3_bg_pos },
{ stage3_bg_ground_draw, stage3_bg_pos },
};
r_clear(BUFFER_COLOR, RGB(0.12, 0.11, 0.10), 1);
stage3d_draw(&stage_3d_context, 120, ARRAY_SIZE(segments), segments);
}
ShaderRule stage3_bg_effects[] = {
stage3_fog,
NULL
};
ShaderRule stage3_postprocess[] = {
stage3_glitch,
NULL
};