shader: optimize and enhance water effects
This commit is contained in:
parent
b0e0041015
commit
50e571e39a
14 changed files with 185 additions and 168 deletions
BIN
resources/00-taisei.pkgdir/gfx/fractal_noise.webp
Normal file
BIN
resources/00-taisei.pkgdir/gfx/fractal_noise.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 263 KiB |
|
@ -3,11 +3,17 @@
|
|||
|
||||
#include "pbr.glslh"
|
||||
|
||||
VARYING(6) vec2 waterTexCoord;
|
||||
|
||||
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;
|
||||
UNIFORM(66) sampler2D water_noisetex;
|
||||
UNIFORM(67) vec3 water_color;
|
||||
UNIFORM(68) vec3 wave_highlight_color;
|
||||
UNIFORM(69) int water_has_bottom_layer;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,37 +1,15 @@
|
|||
|
||||
// smooth noise that is tweaked to look like water
|
||||
// Based on https://www.shadertoy.com/view/Xl2XWz
|
||||
#ifndef I_WATER_H
|
||||
#define I_WATER_H
|
||||
|
||||
float smoothNoise(vec2 p) {
|
||||
vec2 f = fract(p);
|
||||
p -= f;
|
||||
f *= f * (3 - f - f);
|
||||
|
||||
// Intel's sin() function breaks down with values over 1e4 (yes, really)
|
||||
// get rid of some bits here w/o sacrificing the nice effect
|
||||
vec4 a = vec4(0, 1, 27, 28) + p.x + p.y * 27;
|
||||
vec4 b = mod(a, tau);
|
||||
|
||||
// WARNING: Some versions of the Windows AMD driver choke on temp_mat = mat2(temp_vec)
|
||||
vec4 temp_vec = fract(sin(b) * 1e5);
|
||||
mat2 temp_mat = mat2(temp_vec.x, temp_vec.y, temp_vec.z, temp_vec.w);
|
||||
|
||||
return dot(temp_mat * vec2(1 - f.y, f.y), vec2(1 - f.x, f.x));
|
||||
float water_sampleRawNoise(vec2 p) {
|
||||
return texture(water_noisetex, p * (1.0 / 16.0)).x;
|
||||
}
|
||||
|
||||
float fractalNoise(vec2 p) {
|
||||
return
|
||||
smoothNoise(p) * 0.5333 +
|
||||
smoothNoise(p * 2) * 0.2667 +
|
||||
smoothNoise(p * 4) * 0.1333 +
|
||||
smoothNoise(p * 8) * 0.0667;
|
||||
}
|
||||
|
||||
float warpedNoise(vec2 p, float time) {
|
||||
vec2 m = vec2(0.0, -time);
|
||||
float x = fractalNoise(p + m);
|
||||
float y = fractalNoise(p + m.yx + x);
|
||||
float z = fractalNoise(p - m - x);
|
||||
return fractalNoise(p + vec2(x, y) + vec2(y, z) + vec2(z, x) + length(vec3(x, y, z)) * 0.1);
|
||||
float water_sampleWarpedNoise(vec2 p, mat2 s, vec2 m) {
|
||||
float x = water_sampleRawNoise(p + 2.0 * m);
|
||||
float y = water_sampleRawNoise(p - 0.5 * m - x);
|
||||
return water_sampleRawNoise(p - s * vec2(x, y));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,39 +25,45 @@ 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 topLayer(vec3 normal, vec3 pos, vec3 bottom, float highlight);
|
||||
vec3 bottomLayer(mat3 tbn, vec2 uv, vec3 pos);
|
||||
|
||||
void main(void) {
|
||||
vec2 uv = rot(pi/2) * (texCoord + vec2(-0*time, 0));
|
||||
vec2 uv = waterTexCoord;
|
||||
|
||||
float height = warpedNoise(uv, time);
|
||||
vec2 dheightduv = wave_height * dFduv(height, uv.xy);
|
||||
float height = water_sampleWarpedNoise(uv, mat2(2), vec2(-time, 0));
|
||||
vec2 dheightduv = dFduv(height, uv).yx;
|
||||
vec2 dheightduv2 = dheightduv * dheightduv;
|
||||
float wave_highlight = max(dheightduv2.y - 5 * dheightduv2.x, 0);
|
||||
|
||||
mat3 tbn = mat3(normalize(tangent), normalize(bitangent), normalize(normal));
|
||||
vec3 surface_normal = normalize(vec3(-dheightduv, 1));
|
||||
vec3 surface_normal = normalize(vec3(-wave_height * 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;
|
||||
|
||||
vec3 bottom_pos = pos + water_depth * penetration_vec;
|
||||
vec2 bottom_uv = wave_offset +(inverse_modelview * vec4(bottom_pos, 1.0)).xy;
|
||||
if(water_has_bottom_layer == 0) {
|
||||
bottom = water_color * 0.05;
|
||||
} else {
|
||||
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 = bottomLayer(tbn, bottom_uv, bottom_pos);
|
||||
vec3 combined = topLayer(tbn * surface_normal, pos, bottom);
|
||||
vec3 bottom_pos = pos + water_depth * penetration_vec;
|
||||
vec2 bottom_uv = wave_offset + (inverse_modelview * vec4(bottom_pos, 1.0)).xy;
|
||||
bottom = bottomLayer(tbn, bottom_uv, bottom_pos);
|
||||
}
|
||||
|
||||
vec3 combined = topLayer(tbn * surface_normal, pos, bottom, wave_highlight);
|
||||
PBR_Generic_MaybeTonemap(combined, features_mask);
|
||||
|
||||
fragColor = vec4(combined, 1.0);
|
||||
}
|
||||
|
||||
vec3 topLayer(vec3 normal, vec3 pos, vec3 bottom) {
|
||||
|
||||
vec3 topLayer(vec3 normal, vec3 pos, vec3 bottom, float h) {
|
||||
PBRParams p;
|
||||
p.fragPos = pos;
|
||||
p.inv_camera_transform = inv_camera_transform;
|
||||
p.mat.albedo = mix(water_color, water_color + wave_highlight_color, h);
|
||||
p.mat.roughness = 0.1;
|
||||
p.mat.metallic = 0;
|
||||
p.mat.normal = normal;
|
||||
|
|
|
@ -13,6 +13,6 @@ void main(void) {
|
|||
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);
|
||||
texCoord = wave_scale * flip_native_to_bottomleft(texCoordRawIn - wave_offset);
|
||||
waterTexCoord = texCoord + vec2(-time, 0);
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
#include "lib/render_context.glslh"
|
||||
#include "interface/ssr.glslh"
|
||||
#include "lib/util.glslh"
|
||||
#include "lib/water.glslh"
|
||||
#include "lib/frag_util.glslh"
|
||||
|
||||
UNIFORM(5) float wave_height;
|
||||
UNIFORM(6) sampler2D water_noisetex;
|
||||
|
||||
#include "lib/water.glslh"
|
||||
|
||||
const int steps = 10;
|
||||
|
||||
|
@ -53,7 +55,7 @@ vec3 trace_screenspace_reflection(vec3 pos, vec3 n, sampler2D screen_depth, samp
|
|||
|
||||
void main(void) {
|
||||
vec2 uv = flip_native_to_bottomleft(texCoord - wave_offset);
|
||||
float height = wave_height * warpedNoise(uv * 4, time);
|
||||
float height = wave_height * water_sampleWarpedNoise(uv * 4, mat2(2), vec2(time, 0));
|
||||
vec2 dheightduv = dFduv(height, uv);
|
||||
|
||||
mat3 tbn = mat3(normalize(tangent), normalize(bitangent), normalize(normal));
|
||||
|
|
|
@ -1,35 +1,65 @@
|
|||
#version 330 core
|
||||
|
||||
#include "lib/util.glslh"
|
||||
#include "lib/water.glslh"
|
||||
#include "lib/frag_util.glslh"
|
||||
#include "interface/standard.glslh"
|
||||
|
||||
UNIFORM(1) float time;
|
||||
UNIFORM(2) vec4 water_color;
|
||||
UNIFORM(3) vec2 wave_offset;
|
||||
UNIFORM(4) sampler2D water_noisetex;
|
||||
|
||||
#include "lib/water.glslh"
|
||||
|
||||
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);
|
||||
|
||||
float vignette(vec2 uv, float threshold, float intensity) {
|
||||
uv *= 1.0 - uv.yx;
|
||||
return smoothstep(0, threshold, uv.x * uv.y * intensity);
|
||||
}
|
||||
|
||||
// don't try to understand this, it's all fake and horrible
|
||||
|
||||
void main(void) {
|
||||
vec2 uv_raw = texCoord;
|
||||
float v = vignette(uv_raw, 0.75, 20);
|
||||
vec2 uv = flip_native_to_bottomleft(texCoord - wave_offset);
|
||||
|
||||
float n = warpedNoise(uv * 4, time);
|
||||
mat2 m = mat2(0, -1,
|
||||
1, 0);
|
||||
|
||||
float n = water_sampleWarpedNoise(uv * 4, m, vec2(0, -0.25 * time));
|
||||
|
||||
|
||||
vec2 dnduv = dFduv(n, uv)*0.15;
|
||||
vec2 dnduv = v * dFduv(n, uv) * 0.2;
|
||||
vec2 dnduv2 = dnduv * dnduv * 0.5;
|
||||
|
||||
uv = flip_native_to_bottomleft(texCoord);
|
||||
uv += 0.25 * dnduv2;
|
||||
uv = flip_bottomleft_to_native(uv);
|
||||
vec2 reflect_uv = flip_native_to_bottomleft(texCoord);
|
||||
reflect_uv.y += 0.03;
|
||||
reflect_uv -= 0.5;
|
||||
reflect_uv.x *= 3 / (1 + smoothstep(0.5, 1, gl_FragCoord.z)); // yikes
|
||||
reflect_uv += 0.5;
|
||||
reflect_uv.y *= reflect_uv.y;
|
||||
reflect_uv += 0.03 * sign(dnduv) * sqrt(abs(dnduv)) * vec2(0.1, 1); // oof
|
||||
reflect_uv = flip_bottomleft_to_native(reflect_uv);
|
||||
|
||||
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);
|
||||
float reflection_vignette = vignette(clamp(reflect_uv - vec2(0, 0.35), 0, 1), 0.5, 40);
|
||||
reflection_vignette *= vignette(reflect_uv, 0.2, 20);
|
||||
|
||||
fragColor = mix(surface, wave_color, max((dnduv2.y-dnduv2.x*0.25),0) * 0.10);
|
||||
vec4 surface;
|
||||
|
||||
vec2 dUVdx = dFdx(reflect_uv);
|
||||
vec2 dUVdy = dFdy(reflect_uv);
|
||||
|
||||
if(reflection_vignette < 1.0/127.0) {
|
||||
surface = water_color;
|
||||
} else {
|
||||
vec4 reflection = textureGrad(tex, reflect_uv, dUVdx, dUVdy);
|
||||
reflection.rgb = mix(reflection.rgb, water_color.rgb, reflection.a * 0.5);
|
||||
reflection = reflection * reflection_color * (0.5 * reflection_vignette);
|
||||
surface = alphaCompose(water_color, reflection);
|
||||
}
|
||||
|
||||
float w = max((dnduv2.y - dnduv2.x * 0.25), 0) * 0.10;
|
||||
fragColor = mix(surface, wave_color, w);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ void stage1_drawsys_init(void) {
|
|||
cfg.tex_params.wrap.s = TEX_WRAP_CLAMP;
|
||||
cfg.tex_params.wrap.t = TEX_WRAP_CLAMP;
|
||||
|
||||
stage1_draw_data->water_shader = res_shader("stage1_water");
|
||||
stage1_draw_data->water_fbpair.front = stage_add_background_framebuffer(
|
||||
"Stage 1 water FB 1", 0.5, 0.5, 1, &cfg);
|
||||
stage1_draw_data->water_fbpair.back = stage_add_background_framebuffer(
|
||||
|
@ -53,6 +54,7 @@ static bool reflect_draw_predicate(EntityInterface *ent) {
|
|||
switch(ent->draw_layer & ~LAYER_LOW_MASK) {
|
||||
case LAYER_PLAYER_SLAVE:
|
||||
case LAYER_PLAYER_FOCUS:
|
||||
return true;
|
||||
case LAYER_PLAYER_SHOT:
|
||||
case LAYER_PLAYER_SHOT_HIGH:
|
||||
return false;
|
||||
|
@ -60,6 +62,7 @@ static bool reflect_draw_predicate(EntityInterface *ent) {
|
|||
}
|
||||
|
||||
switch(ent->type) {
|
||||
case ENT_TYPE_ID(Player):
|
||||
case ENT_TYPE_ID(Boss):
|
||||
case ENT_TYPE_ID(Enemy):
|
||||
return true;
|
||||
|
@ -80,132 +83,98 @@ static bool reflect_draw_predicate(EntityInterface *ent) {
|
|||
UNREACHABLE;
|
||||
}
|
||||
|
||||
static void stage1_water_draw(vec3 pos) {
|
||||
Stage1DrawData *draw_data = stage1_get_draw_data();
|
||||
|
||||
int pp_quality = config_get_int(CONFIG_POSTPROCESS);
|
||||
|
||||
// don't even ask
|
||||
|
||||
static void stage1_horizon_draw(vec3 pos) {
|
||||
r_state_push();
|
||||
|
||||
r_mat_mv_push();
|
||||
r_mat_mv_translate(0, pos[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_v(pos);
|
||||
r_mat_mv_rotate(1.5 * M_PI, 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_pop();
|
||||
}
|
||||
|
||||
static uint stage1_horizon_pos(Stage3D *s3d, vec3 cam, float maxrange) {
|
||||
vec3 o;
|
||||
glm_vec3_copy(cam, o);
|
||||
o[2] = 0;
|
||||
o[1] += 9700;
|
||||
return stage3d_pos_single(s3d, cam, o, maxrange);
|
||||
}
|
||||
|
||||
static const Color water_color = { 0, 0.08, 0.08, 1 };
|
||||
|
||||
static void stage1_water_render_reflections(void) {
|
||||
r_disable(RCAP_DEPTH_TEST);
|
||||
r_shader("sprite_default");
|
||||
r_blend(BLEND_PREMUL_ALPHA);
|
||||
r_mat_proj_push_ortho(VIEWPORT_W, VIEWPORT_H);
|
||||
ent_draw(reflect_draw_predicate);
|
||||
r_mat_proj_pop();
|
||||
}
|
||||
|
||||
static void stage1_water_render_waves(float pos) {
|
||||
r_shader_ptr(stage1_draw_data->water_shader);
|
||||
r_uniform_float("time", 0.5f * global.frames / (float)FPS);
|
||||
r_uniform_vec4_rgba("water_color", &water_color);
|
||||
r_uniform_vec2("wave_offset", 0, pos / 2400.0f);
|
||||
r_uniform_sampler("water_noisetex", "fractal_noise");
|
||||
r_mat_mv_push();
|
||||
r_mat_mv_scale(VIEWPORT_W, VIEWPORT_H, 1);
|
||||
r_mat_mv_scale(0.01, 0.01, 1);
|
||||
r_mat_mv_translate(-VIEWPORT_W/2, -VIEWPORT_H/2, -0.1);
|
||||
draw_framebuffer_tex(stage1_draw_data->water_fbpair.front, VIEWPORT_W, VIEWPORT_H);
|
||||
r_mat_mv_pop();
|
||||
}
|
||||
|
||||
static void stage1_water_draw(vec3 pos) {
|
||||
r_state_push();
|
||||
r_disable(RCAP_CULL_FACE);
|
||||
|
||||
r_mat_mv_push();
|
||||
r_mat_mv_translate(pos[0], pos[1], 0);
|
||||
|
||||
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(80000, 80000, 1);
|
||||
r_mat_mv_scale(10000, 900000, 1);
|
||||
r_color(&water_color);
|
||||
r_draw_quad();
|
||||
r_color4(1, 1, 1, 1);
|
||||
r_mat_mv_pop();
|
||||
r_state_pop();
|
||||
|
||||
if(pp_quality < 1) {
|
||||
r_state_pop();
|
||||
r_mat_mv_pop();
|
||||
return;
|
||||
}
|
||||
|
||||
r_disable(RCAP_DEPTH_TEST);
|
||||
r_disable(RCAP_CULL_FACE);
|
||||
|
||||
Framebuffer *bg_fb = r_framebuffer_current();
|
||||
FBPair *fbpair = &draw_data->water_fbpair;
|
||||
r_framebuffer(fbpair->back);
|
||||
r_mat_proj_push();
|
||||
set_ortho(VIEWPORT_W, VIEWPORT_H);
|
||||
r_mat_mv_push_identity();
|
||||
|
||||
float hack = (stage_3d_context.cam.rot.v[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, 0, 0), 1);
|
||||
r_shader("sprite_default");
|
||||
|
||||
ent_draw(reflect_draw_predicate);
|
||||
|
||||
r_mat_mv_pop();
|
||||
|
||||
fbpair_swap(fbpair);
|
||||
r_framebuffer(fbpair->back);
|
||||
|
||||
ShaderProgram *water_shader = res_shader("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_vec2(r_shader_uniform(water_shader, "wave_offset"), 0, pos[1] / 2400.0);
|
||||
|
||||
if(pp_quality > 1) {
|
||||
r_shader("blur5");
|
||||
r_uniform_vec2("blur_resolution", VIEWPORT_W, VIEWPORT_H);
|
||||
r_uniform_vec2("blur_direction", 1, 0);
|
||||
draw_framebuffer_tex(fbpair->front, VIEWPORT_W, VIEWPORT_H);
|
||||
fbpair_swap(fbpair);
|
||||
r_framebuffer(fbpair->back);
|
||||
r_uniform_vec2("blur_direction", 0, 1);
|
||||
draw_framebuffer_tex(fbpair->front, VIEWPORT_W, VIEWPORT_H);
|
||||
fbpair_swap(fbpair);
|
||||
r_framebuffer(fbpair->back);
|
||||
switch(config_get_int(CONFIG_POSTPROCESS)) {
|
||||
case 0: break;
|
||||
case 1:
|
||||
// NOTE: we used to render water into a half-res framebuffer here,
|
||||
// but it's no longer beneficial. In fact it's slightly slower.
|
||||
default: {
|
||||
r_mat_mv_translate(0, 0, pos[2]);
|
||||
stage1_water_render_waves(pos[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(pp_quality == 1) {
|
||||
r_mat_mv_push_identity();
|
||||
r_shader_ptr(water_shader);
|
||||
draw_framebuffer_tex(fbpair->front, VIEWPORT_W, VIEWPORT_H);
|
||||
fbpair_swap(fbpair);
|
||||
r_mat_mv_pop();
|
||||
}
|
||||
|
||||
r_mat_proj_pop();
|
||||
|
||||
r_enable(RCAP_DEPTH_TEST);
|
||||
r_disable(RCAP_DEPTH_WRITE);
|
||||
|
||||
r_framebuffer(bg_fb);
|
||||
|
||||
if(pp_quality > 1) {
|
||||
r_shader_ptr(water_shader);
|
||||
} else {
|
||||
r_shader_standard();
|
||||
}
|
||||
|
||||
r_mat_mv_push();
|
||||
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, 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_mat_mv_pop();
|
||||
r_state_pop();
|
||||
}
|
||||
|
||||
static uint stage1_water_pos(Stage3D *s3d, vec3 p, float maxrange) {
|
||||
return stage3d_pos_single(s3d, p, p, maxrange);
|
||||
static uint stage1_water_pos(Stage3D *s3d, vec3 cam, float maxrange) {
|
||||
cmplx sp = VIEWPORT_W*0.5 + VIEWPORT_H*0.6*I;
|
||||
vec3 ray;
|
||||
camera3d_unprojected_ray(&s3d->cam, sp, ray);
|
||||
vec3 o = { 0, 0, 0 };
|
||||
glm_vec3_scale(ray, 3000, ray);
|
||||
glm_vec3_add(cam, ray, o);
|
||||
return stage3d_pos_single(s3d, cam, o, maxrange);
|
||||
}
|
||||
|
||||
static void stage1_smoke_draw(vec3 pos) {
|
||||
|
@ -303,7 +272,7 @@ static void stage1_waterplants_draw(vec3 pos) {
|
|||
}
|
||||
|
||||
static uint stage1_waterplants_pos(Stage3D *s3d, vec3 cam, float maxrange) {
|
||||
vec3 origin = {0,0,-300};
|
||||
vec3 origin = {0,0,0};
|
||||
vec3 step = {0,150,0};
|
||||
return stage3d_pos_ray_farfirst(s3d, cam, origin, step, maxrange * 0.5f, 0.0f);
|
||||
}
|
||||
|
@ -362,7 +331,19 @@ static uint stage1_snow_pos(Stage3D *s3d, vec3 cam, float maxrange) {
|
|||
}
|
||||
|
||||
void stage1_draw(void) {
|
||||
int ppq = config_get_int(CONFIG_POSTPROCESS);
|
||||
|
||||
if(ppq > 0) {
|
||||
r_state_push();
|
||||
r_framebuffer(stage1_draw_data->water_fbpair.back);
|
||||
r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
|
||||
stage1_water_render_reflections();
|
||||
r_state_pop();
|
||||
fbpair_swap(&stage1_draw_data->water_fbpair);
|
||||
}
|
||||
|
||||
Stage3DSegment segs[] = {
|
||||
{ stage1_horizon_draw, stage1_horizon_pos },
|
||||
{ stage1_water_draw, stage1_water_pos },
|
||||
{ stage1_waterplants_draw, stage1_waterplants_pos },
|
||||
{ stage1_snow_draw, stage1_snow_pos },
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
typedef struct Stage1DrawData {
|
||||
FBPair water_fbpair;
|
||||
ShaderProgram *water_shader;
|
||||
|
||||
struct {
|
||||
float near, near_target;
|
||||
|
|
|
@ -100,6 +100,7 @@ static void stage1_preload(void) {
|
|||
"stage1/waterplants",
|
||||
NULL);
|
||||
preload_resources(RES_TEXTURE, RESF_DEFAULT,
|
||||
"fractal_noise",
|
||||
"stage1/horizon",
|
||||
NULL);
|
||||
preload_resources(RES_SHADER_PROGRAM, RESF_DEFAULT,
|
||||
|
|
|
@ -267,6 +267,9 @@ static void stage2_bg_water_draw(vec3 pos) {
|
|||
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);
|
||||
r_uniform_sampler("water_noisetex", "fractal_noise");
|
||||
r_uniform_vec3("water_color", 0.1, 0.2, 0.3);
|
||||
r_uniform_vec3("wave_highlight_color", 0.1, 0.1, 0.1);
|
||||
|
||||
PBREnvironment env = { 0 };
|
||||
stage2_bg_setup_pbr_env(&stage_3d_context.cam, STAGE2_MAX_LIGHTS, &env);
|
||||
|
@ -275,9 +278,13 @@ static void stage2_bg_water_draw(vec3 pos) {
|
|||
r_mat_mv_translate(pos[0], pos[1], pos[2]);
|
||||
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);
|
||||
bool have_bottom = config_get_int(CONFIG_POSTPROCESS) > 1;
|
||||
r_uniform_int("water_has_bottom_layer", have_bottom);
|
||||
if(have_bottom) {
|
||||
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);
|
||||
|
|
|
@ -78,6 +78,7 @@ static void stage2_preload(void) {
|
|||
"part/blast_huge_rays",
|
||||
NULL);
|
||||
preload_resources(RES_TEXTURE, RESF_DEFAULT,
|
||||
"fractal_noise",
|
||||
"ibl_brdf_lut",
|
||||
"stage2/envmap",
|
||||
"stage2/spellbg1",
|
||||
|
|
|
@ -57,7 +57,7 @@ static bool stage4_tonemap(Framebuffer *fb) {
|
|||
}
|
||||
|
||||
static bool should_draw_water(void) {
|
||||
return stage_3d_context.cam.pos[1] < 0 && config_get_int(CONFIG_POSTPROCESS) > 1;
|
||||
return stage_3d_context.cam.pos[1] < 0;
|
||||
}
|
||||
|
||||
static bool stage4_water(Framebuffer *fb) {
|
||||
|
@ -65,6 +65,8 @@ static bool stage4_water(Framebuffer *fb) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: SSR-less version for postprocess < 2
|
||||
|
||||
r_clear(CLEAR_COLOR, RGBA(0, 0, 0, 0), 1);
|
||||
r_mat_proj_push_perspective(stage_3d_context.cam.fovy, stage_3d_context.cam.aspect, stage_3d_context.cam.near, stage_3d_context.cam.far);
|
||||
r_state_push();
|
||||
|
@ -80,6 +82,7 @@ static bool stage4_water(Framebuffer *fb) {
|
|||
r_uniform_float("time", global.frames * 0.002);
|
||||
r_uniform_vec2("wave_offset", -global.frames * 0.0005, 0);
|
||||
r_uniform_float("wave_height", 0.005);
|
||||
r_uniform_sampler("water_noisetex", "fractal_noise");
|
||||
r_color4(0.8, 0.9, 1.0, 1);
|
||||
r_mat_tex_push();
|
||||
r_mat_tex_scale(3, 3, 3);
|
||||
|
@ -109,7 +112,7 @@ static bool stage4_water_composite(Framebuffer *reflections) {
|
|||
// 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
|
||||
// Perhaps a more declarative 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.
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ static void stage4_preload(void) {
|
|||
portrait_preload_face_sprite("kurumi", "normal", RESF_DEFAULT);
|
||||
preload_resources(RES_BGM, RESF_OPTIONAL, "stage4", "stage4boss", NULL);
|
||||
preload_resources(RES_TEXTURE, RESF_DEFAULT,
|
||||
"fractal_noise",
|
||||
"stage4/kurumibg1",
|
||||
"stage4/kurumibg2",
|
||||
NULL);
|
||||
|
|
Loading…
Reference in a new issue