Skip to content

Commit

Permalink
finished shallow water sample
Browse files Browse the repository at this point in the history
  • Loading branch information
RandyGaul committed Mar 23, 2024
1 parent 1e0950f commit e33704e
Show file tree
Hide file tree
Showing 7 changed files with 5,616 additions and 4,948 deletions.
1 change: 1 addition & 0 deletions include/cute_draw.h
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,7 @@ CF_INLINE void draw_quad_fill(Aabb bb, float chubbiness = 0) { cf_draw_quad_fill
CF_INLINE void draw_quad_fill(v2 p0, v2 p1, v2 p2, v2 p3, float chubbiness = 0) { cf_draw_quad_fill2(p0, p1, p2, p3, chubbiness); }
CF_INLINE void draw_box(Aabb bb, float thickness = 1.0f, float chubbiness = 0) { cf_draw_quad(bb, thickness, chubbiness); }
CF_INLINE void draw_box(v2 p0, v2 p1, v2 p2, v2 p3, float thickness = 1.0f, float chubbiness = 0) { cf_draw_quad2(p0, p1, p2, p3, thickness, chubbiness); }
CF_INLINE void draw_box(v2 p, float w, float h, float thickness = 1.0f, float chubbiness = 0) { cf_draw_quad(make_aabb(p, w, h), thickness, chubbiness); }
CF_INLINE void draw_box_fill(Aabb bb, float chubbiness = 0) { cf_draw_quad_fill(bb, chubbiness); }
CF_INLINE void draw_box_fill(v2 p0, v2 p1, v2 p2, v2 p3, float chubbiness = 0) { cf_draw_quad_fill2(p0, p1, p2, p3, chubbiness); }
CF_INLINE void draw_circle(Circle circle, float thickness = 1.0f) { cf_draw_circle(circle, thickness); }
Expand Down
2 changes: 1 addition & 1 deletion include/shaders/draw.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ float distance_triangle(vec2 p, vec2 a, vec2 b, vec2 c)
c = (!is_sprite && !is_text && !is_tri) ? sdf(c, v_col, d - v_radius) : c;

c *= v_alpha;
vec2 screen_position = (v_posH + vec2(1,1)) * 0.5;
vec2 screen_position = (v_posH + vec2(1,1)) * 0.5 * vec2(1,-1);
c = shader(c, v_pos, screen_position, v_user);
if (c.a == 0) discard;
result = c;
Expand Down
96 changes: 88 additions & 8 deletions samples/shallow_water.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ void mount_content_directory_as(const char* dir)
fs_mount(path.c_str(), dir);
}

CF_Pixel* get_noise(int w, int h, float time)
{
float scale = 2.5f;
float lacunarity = 2.0f;
int octaves = 3;
float falloff = 0.5f;
float frequency = 0.5f;
float time_amplitude = 0.05f;
return cf_noise_fbm_pixels_wrapped(w, h, 0, scale, lacunarity, octaves, falloff, time * frequency, time_amplitude);
}

int main(int argc, char* argv[])
{
int options = APP_OPTIONS_DEFAULT_GFX_CONTEXT | APP_OPTIONS_WINDOW_POS_CENTERED | APP_OPTIONS_RESIZABLE;
Expand All @@ -22,8 +33,12 @@ int main(int argc, char* argv[])
mount_content_directory_as("/");
app_init_imgui();

int W = 160;
int H = 120;

CF_Shader shader = CF_MAKE_SOKOL_SHADER(shallow_water_shader);
CF_Canvas offscreen = make_canvas(canvas_defaults(160, 120));
CF_Canvas scene_canvas = make_canvas(canvas_defaults(160, 120));

struct Wavelet
{
Expand All @@ -35,33 +50,98 @@ int main(int argc, char* argv[])

Array<Wavelet> wavelets;

auto add_wavelet = [&](int x, int y) {
Wavelet w;
w.p = V2(x*0.25f - 80, (-y+480)*0.25f - 60);
wavelets.add(w);
struct Spawner
{
v2 p = V2(0,0);
int count = 3;
float opacity = 1.0f;
Routine rt = { };
};

Array<Spawner> spawners;

auto add_wavelet = [&](v2 p, float opacity) {
Wavelet& w = wavelets.add();
w.p = p;
w.opacity = opacity;
};

auto add_spawner = [&](int x, int y) {
Spawner& s = spawners.add();
s.p = V2(x*0.25f - 80, (-y+480)*0.25f - 60);
};

float time = 0;
CF_TextureParams tex_params = texture_defaults(W, H);
tex_params.usage = USAGE_TYPE_STREAM;
CF_Texture noise_tex = make_texture(tex_params);
CF_Sprite scene = make_sprite("/scene.ase");

while (app_is_running()) {
time += CF_DELTA_TIME;
CF_Pixel* noise = get_noise(W, H, time);
update_texture(noise_tex, noise, sizeof(CF_Pixel) * W * H);
cf_free(noise);

app_update();
camera_dimensions(160, 120);

ImGui::Begin("Shallow Water Sample");
static bool show_noise;
ImGui::Checkbox("Show noise", &show_noise);
static bool show_normals;
ImGui::Checkbox("Show normals", &show_normals);
ImGui::End();

if (mouse_just_pressed(MOUSE_BUTTON_LEFT)) {
add_wavelet(mouse_x(), mouse_y());
add_spawner(mouse_x(), mouse_y());
}

for (int i = 0; i < wavelets.size(); ++i) {
for (int i = 0; i < spawners.size(); ++i) {
Spawner& s = spawners[i];
s.opacity = max(0.0f, s.opacity - 0.6f * CF_DELTA_TIME);

rt_begin(s.rt, CF_DELTA_TIME)
{
add_wavelet(s.p, s.opacity);
s.count--;
if (!s.count) {
spawners.unordered_remove(i--);
}
}
rt_wait(0.75f)
{
nav_restart();
}
rt_end();
}

for (int i = 0; i < wavelets.count(); ++i) {
Wavelet& w = wavelets[i];
draw_push_antialias_scale(w.blur);
draw_push_color(make_color(1.0f, 1.0f, 1.0f, w.opacity));
draw_circle(w.p, w.r, 0);
w.r += 10.0f * CF_DELTA_TIME;
w.opacity -= 0.5f * CF_DELTA_TIME;
w.opacity -= 0.4f * CF_DELTA_TIME;
w.blur += 20.0f * CF_DELTA_TIME;
if (w.opacity < 0) {
wavelets.unordered_remove(i++);
wavelets.unordered_remove(i--);
}
}

render_to(offscreen, true);

draw_sprite(scene);
render_to(scene_canvas, true);

render_settings_push_shader(shader);
render_settings_push_texture("wavelets_tex", canvas_get_target(offscreen));
render_settings_push_texture("noise_tex", noise_tex);
render_settings_push_texture("scene_tex", canvas_get_target(scene_canvas));
render_settings_push_uniform("show_noise", show_noise ? 1.0f : 0.0f);
render_settings_push_uniform("show_normals", show_normals ? 1.0f : 0.0f);
draw_push_antialias(false);
draw_box(V2(0,0), (float)W, (float)H);
app_draw_onto_screen();
}

Expand Down
Binary file added samples/shallow_water_data/scene.ase
Binary file not shown.
38 changes: 28 additions & 10 deletions samples/shallow_water_data/shallow_water.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,42 @@
@ctype vec2 CF_V2

@block shader_block
uniform sampler2D water_tex;
uniform sampler2D wavelets_tex;
uniform sampler2D noise_tex;
uniform sampler2D scene_tex;

uniform shader_uniforms {
float amplitude;
float time;
float show_normals;
float show_noise;
};

vec2 normal_from_heightmap(sampler2D tex, vec2 uv)
{
float ha = textureOffset(tex, uv, ivec2(-1, 1)).r;
float hb = textureOffset(tex, uv, ivec2( 1, 1)).r;
float hc = textureOffset(tex, uv, ivec2( 0,-1)).r;
vec2 n = vec2(ha-hc, hb-hc);
return n;
}

vec4 normal_to_color(vec2 n)
{
return vec4(n * 0.5 + 0.5, 1.0, 1.0);
}

vec4 shader(vec4 color, vec2 pos, vec2 uv, vec4 params)
{
vec2 noise_uv = uv;
noise_uv.x *= 640.0 / 128.0;
noise_uv.y *= 480.0 / 128.0;
vec4 noise_c = vec4(texture(noise_tex, noise_uv * 0.5 + time).r - 0.5);
vec2 offset = vec2(1.0/640.0, 1.0/480.0) * noise_c.r * amplitude;
vec4 c = texture(water_tex, uv + offset);
c = show_noise > 0 ? noise_c + 0.5 : c;
vec2 dim = vec2(1.0/160.0,1.0/120.0);
vec2 n = normal_from_heightmap(noise_tex, uv);
vec2 w = normal_from_heightmap(wavelets_tex, uv+n*dim*10.0);
vec4 c = mix(normal_to_color(n), normal_to_color(w), 0.25);
c = texture(scene_tex, uv+(n+w)*dim*10.0);
c = mix(c, vec4(1), length(n+w) > 0.2 ? 0.1 : 0.0);

c = show_normals > 0.0 ? mix(normal_to_color(n), normal_to_color(w), 0.25) : c;

c = show_noise > 0.0 ? texture(noise_tex, uv) : c;

return c;
}
@end
Expand Down
Loading

0 comments on commit e33704e

Please sign in to comment.