stage4: update background
* Add parallax mapping for pebbles * Optimize meshes * Add bevels to bridge and stone path * Misc shading adjustments * Enable anisotropic filtering * Revamp corridor lighting + add torches * Improve water
This commit is contained in:
parent
0f8975d4be
commit
417471b784
41 changed files with 392 additions and 83 deletions
Binary file not shown.
|
@ -1 +1 @@
|
|||
linearize = true
|
||||
anisotropy = 16
|
||||
|
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
linearize = true
|
||||
anisotropy = 16
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
anisotropy = 16
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
anisotropy = 16
|
|
@ -3,3 +3,6 @@ ambient_map = stage4/ground_ambient
|
|||
diffuse_map = stage4/ground_diffuse
|
||||
normal_map = stage4/ground_normal
|
||||
roughness_map = stage4/ground_roughness
|
||||
depth_map = stage4/ground_depth
|
||||
depth_scale = 0.005
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
linearize = True
|
||||
anisotropy = 16
|
||||
|
|
BIN
resources/00-taisei.pkgdir/gfx/stage4/ground_depth.basis
Normal file
BIN
resources/00-taisei.pkgdir/gfx/stage4/ground_depth.basis
Normal file
Binary file not shown.
1
resources/00-taisei.pkgdir/gfx/stage4/ground_depth.tex
Normal file
1
resources/00-taisei.pkgdir/gfx/stage4/ground_depth.tex
Normal file
|
@ -0,0 +1 @@
|
|||
anisotropy = 16
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
linearize = true
|
||||
anisotropy = 16
|
||||
|
|
Binary file not shown.
1
resources/00-taisei.pkgdir/gfx/stage4/ground_normal.tex
Normal file
1
resources/00-taisei.pkgdir/gfx/stage4/ground_normal.tex
Normal file
|
@ -0,0 +1 @@
|
|||
anisotropy = 16
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
anisotropy = 16
|
|
@ -3,3 +3,4 @@ ambient_map = stage4/mansion_ambient
|
|||
diffuse_map = stage4/mansion_diffuse
|
||||
normal_map = stage4/mansion_normal
|
||||
roughness_map = stage4/mansion_roughness
|
||||
|
||||
|
|
Binary file not shown.
BIN
resources/00-taisei.pkgdir/gfx/stage4/mansion_ambient.basis.zst
Normal file
BIN
resources/00-taisei.pkgdir/gfx/stage4/mansion_ambient.basis.zst
Normal file
Binary file not shown.
|
@ -1 +1 @@
|
|||
linearize = True
|
||||
anisotropy = 16
|
||||
|
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
linearize = true
|
||||
anisotropy = 16
|
||||
|
|
Binary file not shown.
1
resources/00-taisei.pkgdir/gfx/stage4/mansion_normal.tex
Normal file
1
resources/00-taisei.pkgdir/gfx/stage4/mansion_normal.tex
Normal file
|
@ -0,0 +1 @@
|
|||
anisotropy = 16
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
anisotropy = 16
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
14
resources/00-taisei.pkgdir/shader/fireparticles.frag.glsl
Normal file
14
resources/00-taisei.pkgdir/shader/fireparticles.frag.glsl
Normal file
|
@ -0,0 +1,14 @@
|
|||
#version 330 core
|
||||
|
||||
#include "lib/defs.glslh"
|
||||
#include "interface/particle_emitter.glslh"
|
||||
|
||||
void main(void) {
|
||||
vec4 c = color * texture(sprite_tex, tex_coord.xy);
|
||||
|
||||
if(all(lessThan(c, vec4(1.0/256.0)))) {
|
||||
discard;
|
||||
}
|
||||
|
||||
fragColor = c;
|
||||
}
|
1
resources/00-taisei.pkgdir/shader/fireparticles.prog
Normal file
1
resources/00-taisei.pkgdir/shader/fireparticles.prog
Normal file
|
@ -0,0 +1 @@
|
|||
objects = fireparticles.vert fireparticles.frag
|
65
resources/00-taisei.pkgdir/shader/fireparticles.vert.glsl
Normal file
65
resources/00-taisei.pkgdir/shader/fireparticles.vert.glsl
Normal file
|
@ -0,0 +1,65 @@
|
|||
#version 330 core
|
||||
|
||||
#include "lib/defs.glslh"
|
||||
#include "lib/util.glslh"
|
||||
#include "lib/render_context.glslh"
|
||||
#include "lib/hash.glslh"
|
||||
#include "interface/particle_emitter.glslh"
|
||||
|
||||
const float min_scale = 0.8;
|
||||
const float max_scale = 1.0;
|
||||
const float min_shrink = 0.2;
|
||||
const float min_lift = 0.9;
|
||||
const float max_lift = 1.2;
|
||||
const float min_ofs = 0.02;
|
||||
const float max_ofs = 0.2;
|
||||
|
||||
const float lift_scale = 3;
|
||||
|
||||
const vec3 v_forward = vec3(0, 0, 1);
|
||||
const vec3 v_right = vec3(1, 0, 0);
|
||||
const vec3 v_up = vec3(0, -1, 0);
|
||||
|
||||
void main(void) {
|
||||
// instance seed is used to seed the time offset of this instance
|
||||
vec3 instance_seed = vec3(seed, float(gl_InstanceID));
|
||||
float t = hash13(instance_seed) + time;
|
||||
|
||||
// particle seed is used to seed the random properties of this particle
|
||||
vec4 particle_seed = vec4(instance_seed, floor(t));
|
||||
vec4 rand = hash44(particle_seed);
|
||||
|
||||
float state = fract(t);
|
||||
float nstate = 1.0 - state;
|
||||
float nstate2 = nstate * nstate;
|
||||
float nstate4 = nstate2 * nstate2;
|
||||
float nstate6 = nstate4 * nstate2;
|
||||
|
||||
float ph = (seed.y - seed.x + t) * (21 + 0.1 * rand.z);
|
||||
float d = 0.2 * nstate2;
|
||||
vec3 up = v_up + d * vec3(sin(ph + seed.y), 0, cos(ph - seed.x));
|
||||
|
||||
float a = rand.x * tau;
|
||||
float sin_a = sin(a);
|
||||
float cos_a = cos(a);
|
||||
|
||||
vec3 p = mat3(mat2(cos_a, sin_a, -sin_a, cos_a)) * position;
|
||||
p *= mix(min_scale, max_scale, rand.y) * mix(min_shrink, 1, nstate2);
|
||||
p += (mix(min_lift, max_lift, rand.z) * lift_scale * state) * up;
|
||||
p += mix(min_ofs, max_ofs, rand.w) * (v_forward * sin_a + v_right * cos_a);
|
||||
|
||||
gl_Position = r_projectionMatrix * r_modelViewMatrix * vec4(p, 1.0);
|
||||
tex_coord.xy = uv_to_region(sprite_tex_region, texCoordRawIn);
|
||||
tex_coord.zw = texCoordRawIn;
|
||||
|
||||
color.rgb = color_base + color_nstate * nstate + color_nstate2 * nstate2;
|
||||
color.rgb *= nstate6;
|
||||
color.a = smoothstep(0.1, 0.5, state);
|
||||
color.a *= color.a;
|
||||
color.a *= color.a;
|
||||
|
||||
float f = 0.075;
|
||||
color *= smoothstep(0, f, state) * nstate2;
|
||||
|
||||
color *= tint;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
#ifndef I_PARTICLE_EMITTER_H
|
||||
#define I_PARTICLE_EMITTER_H
|
||||
|
||||
#ifdef VERT_STAGE
|
||||
ATTRIBUTE(0) vec3 position;
|
||||
ATTRIBUTE(1) vec2 texCoordRawIn;
|
||||
#endif
|
||||
|
||||
#ifdef FRAG_STAGE
|
||||
OUT(0) vec4 fragColor;
|
||||
#endif
|
||||
|
||||
UNIFORM(0) sampler2D sprite_tex;
|
||||
UNIFORM(1) vec4 sprite_tex_region;
|
||||
UNIFORM(2) float time;
|
||||
UNIFORM(3) vec2 seed;
|
||||
UNIFORM(4) vec4 tint;
|
||||
UNIFORM(6) vec3 color_base;
|
||||
UNIFORM(7) vec3 color_nstate;
|
||||
UNIFORM(8) vec3 color_nstate2;
|
||||
|
||||
VARYING(0) vec4 tex_coord;
|
||||
VARYING(1) vec4 color;
|
||||
|
||||
#endif
|
|
@ -26,6 +26,8 @@ glsl_files = files(
|
|||
'extra_tower_apply_mask.frag.glsl',
|
||||
'extra_tower_mask.frag.glsl',
|
||||
'extra_tower_mask.vert.glsl',
|
||||
'fireparticles.frag.glsl',
|
||||
'fireparticles.vert.glsl',
|
||||
'fxaa.frag.glsl',
|
||||
'fxaa.vert.glsl',
|
||||
'glitch.frag.glsl',
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
#include "lib/water.glslh"
|
||||
#include "lib/frag_util.glslh"
|
||||
|
||||
const int steps = 10;
|
||||
UNIFORM(5) float wave_height;
|
||||
|
||||
const int steps = 10;
|
||||
|
||||
// way to optimize: do projection matrix in the vertex shader
|
||||
vec3 pos_to_texcoord(vec3 pos) {
|
||||
|
@ -15,27 +16,18 @@ vec3 pos_to_texcoord(vec3 pos) {
|
|||
return 0.5*tmp.xyz/tmp.w + vec3(0.5);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec2 uv = flip_native_to_bottomleft(texCoord - wave_offset);
|
||||
|
||||
float height = 0.01*warpedNoise(uv * 4, time);
|
||||
|
||||
vec2 dheightduv = dFduv(height, uv);
|
||||
|
||||
mat3 tbn = mat3(normalize(tangent), normalize(bitangent), normalize(normal));
|
||||
vec3 n = normalize(tbn*vec3(-dheightduv, 1));
|
||||
|
||||
vec3 trace_screenspace_reflection(vec3 pos, vec3 n, sampler2D screen_depth, sampler2D screen_color) {
|
||||
vec3 reflected_ray = reflect(pos, n);
|
||||
reflected_ray /= length(reflected_ray.xy);
|
||||
float step_size = 15./steps;
|
||||
const float step_size = 15.0 / steps;
|
||||
|
||||
fragColor = r_color;
|
||||
vec3 color = vec3(0);
|
||||
int ihit = 0;
|
||||
|
||||
for(int i = 1; i < steps; i++) {
|
||||
vec3 raypos = pos + i * step_size * reflected_ray;
|
||||
vec3 raycoord = pos_to_texcoord(raypos);
|
||||
float bgdepth = texture(depth, raycoord.xy).r;
|
||||
float bgdepth = texture(screen_depth, raycoord.xy).r;
|
||||
if(bgdepth < raycoord.z) {
|
||||
ihit = i;
|
||||
break; // sorry gpu
|
||||
|
@ -43,15 +35,30 @@ void main(void) {
|
|||
}
|
||||
|
||||
if(ihit == 0) {
|
||||
return;
|
||||
return color;
|
||||
}
|
||||
|
||||
for(int j = 0; j < steps; j++) {
|
||||
vec3 raypos = pos + (ihit-1+j*1.0/(steps-1)) * step_size * reflected_ray;
|
||||
vec3 raycoord = pos_to_texcoord(raypos);
|
||||
float bgdepth = texture(depth, raycoord.xy).r;
|
||||
float bgdepth = texture(screen_depth, raycoord.xy).r;
|
||||
if(bgdepth < raycoord.z) {
|
||||
fragColor += 0.8 * texture(tex, raycoord.xy);
|
||||
color += 0.8 * texture(screen_color, raycoord.xy).rgb;
|
||||
break; // sorry gpu
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec2 uv = flip_native_to_bottomleft(texCoord - wave_offset);
|
||||
float height = wave_height * warpedNoise(uv * 4, time);
|
||||
vec2 dheightduv = dFduv(height, uv);
|
||||
|
||||
mat3 tbn = mat3(normalize(tangent), normalize(bitangent), normalize(normal));
|
||||
vec3 n = normalize(tbn*vec3(-dheightduv, 1));
|
||||
|
||||
fragColor = r_color;
|
||||
fragColor.rgb *= trace_screenspace_reflection(pos, n, depth, tex);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ TASK(update_stage_3d) {
|
|||
|
||||
TASK(animate_bg_fullstage) {
|
||||
Camera3D *cam = &stage_3d_context.cam;
|
||||
cam->far = 300;
|
||||
|
||||
cam->pos[2] = -1.8;
|
||||
cam->pos[1] = -30;
|
||||
|
@ -44,36 +43,66 @@ TASK(animate_bg_fullstage) {
|
|||
INVOKE_TASK(common_easing_animate,&cam->vel[1], 0.06, 200, glm_ease_quad_in);
|
||||
}
|
||||
|
||||
void stage4_bg_init_fullstage() {
|
||||
static void stage4_bg_init_common(void) {
|
||||
Stage4DrawData *draw_data = stage4_get_draw_data();
|
||||
draw_data->ambient_color = *RGB(0.3, 0.3, 0.3);
|
||||
stage_3d_context.cam.far = 300;
|
||||
|
||||
glm_vec3_copy((vec3) { 0.8f, 0.4f, 0.2f }, draw_data->corridor.torch_light.base);
|
||||
draw_data->corridor.torch_light.r_factor = 0.1;
|
||||
draw_data->corridor.torch_light.g_factor = 0.05;
|
||||
|
||||
// nstate goes from 1 to 0 linearly as the particle evolves
|
||||
// particle color = color_base + (nstate * color_nstate) + (nstate^2 * color_nstate2)
|
||||
glm_vec3_copy((vec3) { 10.0f, 0.0f, 0.0f }, draw_data->corridor.torch_particles.c_base);
|
||||
glm_vec3_copy((vec3) { 0.0f, 0.0f, 0.8f }, draw_data->corridor.torch_particles.c_nstate);
|
||||
glm_vec3_copy((vec3) { 0.0f, 3.2f, 0.0f }, draw_data->corridor.torch_particles.c_nstate2);
|
||||
}
|
||||
|
||||
void stage4_bg_init_fullstage(void) {
|
||||
stage4_bg_init_common();
|
||||
INVOKE_TASK(update_stage_3d);
|
||||
INVOKE_TASK(animate_bg_fullstage);
|
||||
}
|
||||
|
||||
void stage4_bg_init_spellpractice(void) {
|
||||
stage_3d_context.cam.far = 300;
|
||||
stage4_bg_init_common();
|
||||
|
||||
stage_3d_context.cam.pos[2] = 4;
|
||||
stage_3d_context.cam.pos[1] = 200;
|
||||
stage_3d_context.cam.rot.v[0] = 80;
|
||||
stage_3d_context.cam.vel[1] = 0.06;
|
||||
|
||||
stage_3d_context.cam.vel[1] = 0.05;
|
||||
stage4_bg_redden_corridor();
|
||||
INVOKE_TASK(update_stage_3d);
|
||||
}
|
||||
|
||||
TASK(redden_corridor) {
|
||||
Stage4DrawData *draw_data = stage4_get_draw_data();
|
||||
int t = 100;
|
||||
|
||||
for(int i = 0; i < t; i++) {
|
||||
color_approach(&draw_data->ambient_color, RGB(1, 0, 0), 1.0f / t);
|
||||
YIELD;
|
||||
}
|
||||
// INVOKE_TASK_DELAYED(60, common_call_func, stage4_bg_redden_corridor);
|
||||
}
|
||||
|
||||
void stage4_bg_redden_corridor(void) {
|
||||
INVOKE_TASK(redden_corridor);
|
||||
// TODO: maybe a nicer transition effect based on proximity of the lights
|
||||
|
||||
Stage4DrawData *draw_data = stage4_get_draw_data();
|
||||
INVOKE_TASK(common_easing_animate_vec3,
|
||||
&draw_data->corridor.torch_light.base,
|
||||
{ 0.8f, 0.1f, 0.2f },
|
||||
60,
|
||||
glm_ease_quad_out
|
||||
);
|
||||
INVOKE_TASK(common_easing_animate_vec3,
|
||||
&draw_data->corridor.torch_particles.c_base,
|
||||
{ 10.0f, 0.0, 0.0f },
|
||||
60,
|
||||
glm_ease_quad_out
|
||||
);
|
||||
INVOKE_TASK(common_easing_animate_vec3,
|
||||
&draw_data->corridor.torch_particles.c_nstate,
|
||||
{ 10.0f, 0.2f, 0.3f },
|
||||
80,
|
||||
glm_ease_quad_out
|
||||
);
|
||||
INVOKE_TASK(common_easing_animate_vec3,
|
||||
&draw_data->corridor.torch_particles.c_nstate2,
|
||||
{ 10.0f, 0.2f, 0.2f },
|
||||
56,
|
||||
glm_ease_quad_out
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
#include "global.h"
|
||||
#include "util/glm.h"
|
||||
|
||||
#define LIGHT_OFS { 2.7f, 4.86f, 0.3f }
|
||||
#define CORRIDOR_POS { 0.0f, 25.0f, 3.0f }
|
||||
#define TORCHLIGHT_CLOCK (global.frames / 30.0f)
|
||||
|
||||
static Stage4DrawData *stage4_draw_data;
|
||||
|
||||
Stage4DrawData *stage4_get_draw_data(void) {
|
||||
|
@ -20,17 +24,34 @@ Stage4DrawData *stage4_get_draw_data(void) {
|
|||
}
|
||||
|
||||
static bool stage4_fog(Framebuffer *fb) {
|
||||
float f = 0;
|
||||
r_state_push();
|
||||
r_blend(BLEND_NONE);
|
||||
|
||||
// NOTE: this is applied in linear HDR space, before tonemapping
|
||||
|
||||
Color c = *RGBA(0.05, 0.0, 0.01, 1.0);
|
||||
|
||||
r_shader("zbuf_fog");
|
||||
r_uniform_sampler("depth", r_framebuffer_get_attachment(fb, FRAMEBUFFER_ATTACH_DEPTH));
|
||||
r_uniform_vec4("fog_color", 9.0*f+0.1, 0.0, 0.1-f, 1.0);
|
||||
r_uniform_vec4_rgba("fog_color", &c);
|
||||
r_uniform_float("start", 0.4);
|
||||
r_uniform_float("end", 1);
|
||||
r_uniform_float("exponent", 50.0);
|
||||
r_uniform_float("exponent", 20.0);
|
||||
r_uniform_float("curvature", 0);
|
||||
draw_framebuffer_tex(fb, VIEWPORT_W, VIEWPORT_H);
|
||||
r_shader_standard();
|
||||
|
||||
r_state_pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stage4_tonemap(Framebuffer *fb) {
|
||||
r_state_push();
|
||||
r_blend(BLEND_NONE);
|
||||
r_shader("tonemap");
|
||||
r_uniform_vec3("exposure", 1, 1, 1);
|
||||
draw_framebuffer_tex(fb, VIEWPORT_W, VIEWPORT_H);
|
||||
r_state_pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -52,14 +73,18 @@ static bool stage4_water(Framebuffer *fb) {
|
|||
r_mat_mv_translate(0, 3, -0.6);
|
||||
r_enable(RCAP_DEPTH_TEST);
|
||||
|
||||
r_mat_mv_scale(20,-20,10);
|
||||
r_mat_mv_scale(15, -10, 1);
|
||||
r_shader("ssr_water");
|
||||
r_uniform_sampler("depth", r_framebuffer_get_attachment(fb, FRAMEBUFFER_ATTACH_DEPTH));
|
||||
r_uniform_sampler("tex", r_framebuffer_get_attachment(fb, FRAMEBUFFER_ATTACH_COLOR0));
|
||||
r_uniform_float("time", global.frames * 0.002);
|
||||
r_uniform_vec2("wave_offset", -global.frames * 0.0005, 0);
|
||||
r_color4(0, 0.01, 0.01, 1);
|
||||
r_uniform_float("wave_height", 0.005);
|
||||
r_color4(0.8, 0.9, 1.0, 1);
|
||||
r_mat_tex_push();
|
||||
r_mat_tex_scale(3, 3, 3);
|
||||
r_draw_quad();
|
||||
r_mat_tex_pop();
|
||||
|
||||
r_mat_mv_pop();
|
||||
r_state_pop();
|
||||
|
@ -73,17 +98,40 @@ static bool stage4_water_composite(Framebuffer *reflections) {
|
|||
return false;
|
||||
}
|
||||
|
||||
r_shader("alpha_discard");
|
||||
r_state_push();
|
||||
|
||||
// NOTE: Ideally, we should copy depth from the previous framebuffer here,
|
||||
// otherwise the fog shader will destroy parts of the water that were composed
|
||||
// over the void. We can get away without a proper copy in this case by simply
|
||||
// enabling unconditional depth writes. This way, fragments that were not
|
||||
// rejected by the alpha threshold test will get a depth value of 0.5 from the
|
||||
// screen-space quad. This effectively makes the water fragments completely
|
||||
// exempt from the fog effect, which is not 100% correct, but the error is not
|
||||
// noticeable with our camera and fog settings.
|
||||
|
||||
// Perhaps a more delcarative post-processing system would be nice, so that we
|
||||
// could specify which passes consume and/or update depth, and have the depth
|
||||
// buffer copied automatically when needed.
|
||||
|
||||
r_enable(RCAP_DEPTH_TEST);
|
||||
r_depth_func(DEPTH_ALWAYS);
|
||||
r_blend(BLEND_NONE);
|
||||
|
||||
r_shader("alpha_discard");
|
||||
r_uniform_float("threshold", 1);
|
||||
draw_framebuffer_tex(reflections, VIEWPORT_W, VIEWPORT_H);
|
||||
|
||||
r_state_pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void torchlight(float t, PointLight3D *light);
|
||||
|
||||
static void stage4_bg_setup_pbr_lighting_outdoors(Camera3D *cam) {
|
||||
PointLight3D lights[] = {
|
||||
{ { 0, 0, 0 }, { 3, 4, 5 } },
|
||||
{ { 0, 25, 3 }, { 4, 20, 22 } },
|
||||
{ { 0, 25, 3 }, { 4*0, 20*0, 22*0} },
|
||||
};
|
||||
|
||||
vec3 r;
|
||||
|
@ -97,33 +145,54 @@ static void stage4_bg_setup_pbr_lighting_outdoors(Camera3D *cam) {
|
|||
static void stage4_bg_setup_pbr_env_outdoors(Camera3D *cam, PBREnvironment *env) {
|
||||
stage4_bg_setup_pbr_lighting_outdoors(cam);
|
||||
glm_vec3_broadcast(1.0f, env->ambient_color);
|
||||
env->disable_tonemap = true;
|
||||
}
|
||||
|
||||
static void torchlight(float t, PointLight3D *light) {
|
||||
uint32_t prng = float_to_bits(light->pos[0]) ^ float_to_bits(light->pos[1]);
|
||||
float t_ofs = (float)(splitmix32(&prng) / (double)UINT32_MAX);
|
||||
t += 32.124 * t_ofs;
|
||||
|
||||
float o0 = (float)(splitmix32(&prng) / (double)UINT32_MAX);
|
||||
float o1 = (float)(splitmix32(&prng) / (double)UINT32_MAX);
|
||||
float o2 = (float)(splitmix32(&prng) / (double)UINT32_MAX);
|
||||
float o3 = (float)(splitmix32(&prng) / (double)UINT32_MAX);
|
||||
float o4 = (float)(splitmix32(&prng) / (double)UINT32_MAX);
|
||||
float o5 = (float)(splitmix32(&prng) / (double)UINT32_MAX);
|
||||
|
||||
float r = powf(psinf(2*t+o0), 2) + powf(pcosf(4.43*t+o1), 4) + powf(psinf(5*t+o2), 21);
|
||||
float g = powf(psinf(1.65*t+o3), 2) + powf(pcosf(5.21*t+o4), 3) + powf(psinf(-3*t+o5), 12);
|
||||
|
||||
r = fmaxf(r, g);
|
||||
r = powf(tanh(r), 5);
|
||||
g = powf(tanh(g), 5);
|
||||
|
||||
vec3 c;
|
||||
vec3 rg = {
|
||||
r * stage4_draw_data->corridor.torch_light.r_factor,
|
||||
g * stage4_draw_data->corridor.torch_light.g_factor,
|
||||
0.0f
|
||||
};
|
||||
glm_vec3_add(stage4_draw_data->corridor.torch_light.base, rg, c);
|
||||
glm_vec3_scale(c, 20 + sinf(t) + cosf(2*t), light->radiance);
|
||||
}
|
||||
|
||||
static void stage4_bg_setup_pbr_lighting_indoors(Camera3D *cam, vec3 pos) {
|
||||
float xoff = 3.0f;
|
||||
float zoff = 1.3f;
|
||||
vec3 off = LIGHT_OFS;
|
||||
|
||||
PointLight3D lights[] = {
|
||||
{ { -xoff, pos[1], pos[2]+zoff }, { 1, 20, 20 } },
|
||||
{ { xoff, pos[1], pos[2]+zoff }, { 1, 20, 20 } },
|
||||
{ { -xoff, pos[1]-10, pos[2]+zoff }, { 1, 20, 20 } },
|
||||
{ { xoff, pos[1]-10, pos[2]+zoff }, { 1, 20, 20 } },
|
||||
{ { -xoff, pos[1]+10, pos[2]+zoff }, { 1, 20, 20 } },
|
||||
{ { xoff, pos[1]+10, pos[2]+zoff }, { 1, 20, 20 } },
|
||||
{ { -off[0], off[1]+pos[1], pos[2]+off[2] } },
|
||||
{ { off[0], off[1]+pos[1], pos[2]+off[2] } },
|
||||
{ { -off[0], off[1]+pos[1]-10, pos[2]+off[2] } },
|
||||
{ { off[0], off[1]+pos[1]-10, pos[2]+off[2] } },
|
||||
{ { -off[0], off[1]+pos[1]+10, pos[2]+off[2] } },
|
||||
{ { off[0], off[1]+pos[1]+10, pos[2]+off[2] } },
|
||||
};
|
||||
|
||||
float t = TORCHLIGHT_CLOCK;
|
||||
|
||||
for(int i = 0; i < ARRAY_SIZE(lights); i++) {
|
||||
float t = global.frames * 0.02f;
|
||||
float mod1 = cosf(13095434.0f * lights[i].pos[1]);
|
||||
float mod2 = sinf(1242435.0f * lights[i].pos[0] * lights[i].pos[1]);
|
||||
|
||||
float f = (
|
||||
sinf((1.0f + mod1) * t) +
|
||||
sinf((2.35f + mod2) * t + mod1) +
|
||||
sinf((3.1257f + mod1 * mod2) * t + mod2)
|
||||
) / 3.0f;
|
||||
|
||||
glm_vec3_scale(lights[i].radiance, 0.6f + 0.4f * f, lights[i].radiance);
|
||||
torchlight(t, lights + i);
|
||||
}
|
||||
|
||||
camera3d_set_point_light_uniforms(cam, ARRAY_SIZE(lights), lights);
|
||||
|
@ -131,13 +200,13 @@ static void stage4_bg_setup_pbr_lighting_indoors(Camera3D *cam, vec3 pos) {
|
|||
|
||||
static void stage4_bg_setup_pbr_env_indoors(Camera3D *cam, vec3 pos, PBREnvironment *env) {
|
||||
stage4_bg_setup_pbr_lighting_indoors(cam, pos);
|
||||
glm_vec3_copy(&stage4_draw_data->ambient_color.r, env->ambient_color);
|
||||
log_debug("%0.2f %0.2f %0.2f", env->ambient_color[0], env->ambient_color[1], env->ambient_color[2]);
|
||||
glm_vec3_copy(stage4_draw_data->ambient_color.rgb, env->ambient_color);
|
||||
env->disable_tonemap = true;
|
||||
}
|
||||
|
||||
static uint stage4_lake_pos(Stage3D *s3d, vec3 pos, float maxrange) {
|
||||
vec3 p = {0, 0, 0};
|
||||
return single3dpos(s3d, pos, maxrange, p);
|
||||
static uint stage4_lake_pos(Stage3D *s3d, vec3 cam, float maxrange) {
|
||||
vec3 orig = {0, 0, 0};
|
||||
return stage3d_pos_single(s3d, cam, orig, 35);
|
||||
}
|
||||
|
||||
static void stage4_lake_draw(vec3 pos) {
|
||||
|
@ -157,19 +226,16 @@ static void stage4_lake_draw(vec3 pos) {
|
|||
r_state_pop();
|
||||
}
|
||||
|
||||
static uint stage4_corridor_pos(Stage3D *s3d, vec3 pos, float maxrange) {
|
||||
vec3 p = {0, 25, 3};
|
||||
static uint stage4_corridor_pos(Stage3D *s3d, vec3 cam, float maxrange) {
|
||||
vec3 p = CORRIDOR_POS;
|
||||
vec3 r = {0, 10, 0};
|
||||
return stage3d_pos_ray_nearfirst(s3d, cam, p, r, maxrange, 0);
|
||||
}
|
||||
|
||||
uint num = linear3dpos(s3d, pos, maxrange, p, r);
|
||||
|
||||
for(uint i = 0; i < num; ++i) {
|
||||
if(s3d->pos_buffer[i][1] < p[1]) {
|
||||
s3d->pos_buffer[i][1] = -9000;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
static uint stage4_flames_pos(Stage3D *s3d, vec3 cam, float maxrange) {
|
||||
vec3 p = CORRIDOR_POS;
|
||||
vec3 r = {0, 10, 0};
|
||||
return stage3d_pos_ray_farfirst(s3d, cam, p, r, maxrange, 0);
|
||||
}
|
||||
|
||||
static void stage4_corridor_draw(vec3 pos) {
|
||||
|
@ -188,13 +254,78 @@ static void stage4_corridor_draw(vec3 pos) {
|
|||
r_state_pop();
|
||||
}
|
||||
|
||||
static void stage4_flames_draw(vec3 pos) {
|
||||
r_state_push();
|
||||
r_mat_mv_push();
|
||||
|
||||
Camera3D *cam = &stage_3d_context.cam;
|
||||
float dist = pos[1] - cam->pos[1];
|
||||
|
||||
float dmin = 8;
|
||||
float dmax = 128;
|
||||
float lod = 1.0f - clamp((dist - dmin) / (dmax - dmin), 0.0f, 1.0f);
|
||||
|
||||
uint imin = 16;
|
||||
uint imax = 256;
|
||||
uint instances = lerpf(imin, imax, lod * lod * lod * lod);
|
||||
|
||||
float al = fminf(1.0f, 64.0f / instances);
|
||||
|
||||
r_blend(BLEND_PREMUL_ALPHA);
|
||||
r_disable(RCAP_DEPTH_WRITE);
|
||||
|
||||
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_vec("color_base", stage4_draw_data->corridor.torch_particles.c_base);
|
||||
r_uniform_vec3_vec("color_nstate", stage4_draw_data->corridor.torch_particles.c_nstate);
|
||||
r_uniform_vec3_vec("color_nstate2", stage4_draw_data->corridor.torch_particles.c_nstate2);
|
||||
r_uniform_vec4("tint", al, al, al, al);
|
||||
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);
|
||||
|
||||
vec3 ofs = LIGHT_OFS;
|
||||
vec3 p;
|
||||
mat4 *mv;
|
||||
|
||||
glm_vec3_add(pos, ofs, p);
|
||||
r_uniform_vec2_vec("seed", p);
|
||||
r_mat_mv_push();
|
||||
r_mat_mv_translate_v(p);
|
||||
mv = r_mat_mv_current_ptr();
|
||||
glm_mul(*mv, stage4_draw_data->fire_emitter_transform, *mv);
|
||||
r_draw_model_ptr(quad, instances, 0);
|
||||
r_mat_mv_pop();
|
||||
|
||||
ofs[0] *= -1.0f;
|
||||
|
||||
glm_vec3_add(pos, ofs, p);
|
||||
r_uniform_vec2_vec("seed", p);
|
||||
r_mat_mv_push();
|
||||
r_mat_mv_translate_v(p);
|
||||
mv = r_mat_mv_current_ptr();
|
||||
glm_mul(*mv, stage4_draw_data->fire_emitter_transform, *mv);
|
||||
r_draw_model_ptr(quad, instances, 0);
|
||||
r_mat_mv_pop();
|
||||
|
||||
r_mat_mv_pop();
|
||||
r_state_pop();
|
||||
}
|
||||
|
||||
void stage4_draw(void) {
|
||||
Stage3DSegment segs[] = {
|
||||
{ stage4_lake_draw, stage4_lake_pos },
|
||||
{ stage4_corridor_draw, stage4_corridor_pos },
|
||||
{ stage4_flames_draw, stage4_flames_pos },
|
||||
};
|
||||
|
||||
stage3d_draw(&stage_3d_context, 400, ARRAY_SIZE(segs), segs);
|
||||
stage3d_draw(&stage_3d_context, 240, ARRAY_SIZE(segs), segs);
|
||||
}
|
||||
|
||||
void stage4_drawsys_init(void) {
|
||||
|
@ -204,6 +335,12 @@ void stage4_drawsys_init(void) {
|
|||
pbr_load_model(&stage4_draw_data->models.corridor, "stage4/corridor", "stage4/corridor");
|
||||
pbr_load_model(&stage4_draw_data->models.ground, "stage4/ground", "stage4/ground");
|
||||
pbr_load_model(&stage4_draw_data->models.mansion, "stage4/mansion", "stage4/mansion");
|
||||
|
||||
mat4 *m = &stage4_draw_data->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);
|
||||
}
|
||||
|
||||
void stage4_drawsys_shutdown(void) {
|
||||
|
@ -216,5 +353,6 @@ ShaderRule stage4_bg_effects[] = {
|
|||
stage4_water,
|
||||
stage4_water_composite,
|
||||
stage4_fog,
|
||||
stage4_tonemap,
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -22,6 +22,22 @@ typedef struct Stage4DrawData {
|
|||
PBRModel ground;
|
||||
PBRModel mansion;
|
||||
} models;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
vec3 c_base;
|
||||
vec3 c_nstate;
|
||||
vec3 c_nstate2;
|
||||
} torch_particles;
|
||||
|
||||
struct {
|
||||
vec3 base;
|
||||
float r_factor;
|
||||
float g_factor;
|
||||
} torch_light;
|
||||
} corridor;
|
||||
|
||||
mat4 fire_emitter_transform;
|
||||
} Stage4DrawData;
|
||||
|
||||
void stage4_drawsys_init(void);
|
||||
|
|
Loading…
Reference in a new issue