From e98c524ac0706e366e6c4bbd8e4d258af25ef312 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Sat, 24 Dec 2022 18:52:02 -0800 Subject: [PATCH] Make thruster smoke look like fire, rendertarget --- fire.glsl | 48 ++++++++++++++ flight.rdbg | Bin 1682 -> 1659 bytes main.c | 175 +++++++++++++++++++++++++++++++++++++++++--------- shadergen.bat | 3 +- 4 files changed, 193 insertions(+), 33 deletions(-) create mode 100644 fire.glsl diff --git a/fire.glsl b/fire.glsl new file mode 100644 index 0000000..c963aad --- /dev/null +++ b/fire.glsl @@ -0,0 +1,48 @@ +@module fire + +@vs vs +in vec4 coord; +out vec2 texUV; +void main() { + gl_Position = vec4(coord.xy, 0.0, 1.0); + texUV = coord.zw; +} +@end + +@fs fs +uniform sampler2D iChannel0; +uniform fs_params { + vec4 iColor; +}; +in vec2 texUV; +out vec4 fragColor; + +void main() { + vec4 tex_color = texture(iChannel0,texUV); + + // https://airtightinteractive.com/util/hex-to-glsl/ + float how_faded = clamp((1.0 - tex_color.a) - 0.32, 0.0, 1.0); + vec3 edge_color = mix(vec3(1.0, 0.0, 0.0), vec3(0.929,0.624,0.439), how_faded); + vec3 body_color = vec3(0.933,0.788,0.69); + if(tex_color.a <= 0.05) + { + fragColor = vec4(0.0); + } else { + fragColor = vec4(mix(edge_color, body_color, tex_color.a), mix(1.0, 0.0, clamp((1.0 - tex_color.a) - 0.2, 0.0, 1.0))); + } + /* + vec3 smoke_body = + vec3 smoke_edge = tex_color.rgb; + + if(tex_color.a <= 0.05) + { + fragColor = vec4(0.0); + } else { + fragColor = vec4(mix(smoke_edge, smoke_body, tex_color.a), 1.0); + } + */ + +} +@end + +@program program vs fs diff --git a/flight.rdbg b/flight.rdbg index 47236f407e349c515775093c50ae4192feae6fa4..b6e53d5dfa12030a01eb0b6c3b8d395c449a698e 100644 GIT binary patch delta 317 zcmbQl`PQsYQCp6F2BGGEEL=abN|yje&7up-CK)Tb^1l zFfakdC4smgvq0A_ITvU^eolT-d|G}{ZemGsbY?6_GO?s2J~KBRqM#tNA~gr90HnLz yV72*$gv&-CHpAwXEHRASASMViGB8aRWK*21z{bYI4B|5~a)6|uf*g~R*bD$WT2~wZ delta 299 zcmey(Gl_RX0Si9^1H(G$#)W8s<1%Phm_io_FR)=Ng_3$bS;7NqJWyCJC&-fRW{b;LwG diff --git a/main.c b/main.c index 221bd6d..1bdaafc 100644 --- a/main.c +++ b/main.c @@ -37,6 +37,7 @@ #include "profiling.h" // shaders +#include "fire.gen.h" #include "goodpixel.gen.h" #include "horizontal_lightning.gen.h" #include "hueshift.gen.h" @@ -45,6 +46,7 @@ static sg_pipeline hueshift_pipeline; static sg_pipeline goodpixel_pipeline; static sg_pipeline lightning_pipeline; static sg_pipeline horizontal_lightning_pipeline; +static sg_pipeline fire_pipeline; static struct GameState gs = {0}; static int my_player_index = -1; @@ -139,6 +141,9 @@ static sg_image image_orb_frozen; static sg_image image_radardot; static sg_image image_pip; +static sg_image fire_rendertarget; +static sg_pass fire_pass; + static enum BoxType toolbar[TOOLBAR_SLOTS] = { BoxHullpiece, BoxThruster, @@ -452,8 +457,6 @@ void recalculate_camera_pos() } } -// drawing - #define WHITE \ (Color) \ { \ @@ -519,7 +522,7 @@ void set_color_values(double r, double g, double b, double a) } // @Robust make the transform stack actually use double precision logic, and -// fix the debug drawing after that as well +// fix the debug draw after that as well void translate(double x, double y) { sgp_translate((float)x, (float)y); @@ -547,6 +550,17 @@ void draw_textured_rect(double x, double y, double w, double h) sgp_draw_textured_rect((float)x, (float)y, (float)w, (float)h); } +static void transform_worldspace_zoom(double width, double height) +{ + translate(width / 2, height / 2); + scale_at(zoom, -zoom, 0.0, 0.0); +} + +static void transform_worldspace_camera() +{ + translate(-camera_pos.x, -camera_pos.y); +} + static void init(void) { fopen_s(&log_file, "astris_log.txt", "a"); @@ -747,6 +761,55 @@ static void init(void) quit_with_popup("Couldn't make a shader! Uhhh ooooohhhhhh!!!", "Shader error BONED"); } } + + { + sgp_pipeline_desc pip_desc = { + .shader = *fire_program_shader_desc(sg_query_backend()), + .blend_mode = SGP_BLENDMODE_BLEND, + }; + + fire_pipeline = sgp_make_pipeline(&pip_desc); + sg_resource_state errstate = sg_query_pipeline_state(fire_pipeline); + if (errstate != SG_RESOURCESTATE_VALID) + { + Log("Failed to make fire pipeline\n"); + quit_with_popup("Couldn't make a shader! Uhhh ooooohhhhhh!!!", "Shader error BONED"); + } + } + } + + // initialize buffers + { + fire_rendertarget = sg_make_image( + &(sg_image_desc){ + .width = sapp_width(), + .height = sapp_height(), + .pixel_format = SG_PIXELFORMAT_BGRA8, + .min_filter = SG_FILTER_LINEAR, + .mag_filter = SG_FILTER_LINEAR, + .wrap_u = SG_WRAP_CLAMP_TO_EDGE, + .render_target = true, + }); + sg_image fire_depth = sg_make_image( + &(sg_image_desc){ + .width = sapp_width(), + .height = sapp_height(), + .pixel_format = SG_PIXELFORMAT_DEPTH_STENCIL, + .min_filter = SG_FILTER_LINEAR, + .mag_filter = SG_FILTER_LINEAR, + .wrap_u = SG_WRAP_CLAMP_TO_EDGE, + .render_target = true, + }); + flight_assert(fire_rendertarget.id != SG_INVALID_ID); + fire_pass = sg_make_pass(&(sg_pass_desc){ + .color_attachments[0] = (sg_pass_attachment_desc){ + .image = fire_rendertarget, + }, + .depth_stencil_attachment = (sg_pass_attachment_desc){ + .image = fire_depth, + } + + }); } // images loading @@ -1652,8 +1715,7 @@ static void frame(void) case ENET_EVENT_TYPE_RECEIVE: { total_bytes_received += event.packet->dataLength; - unsigned char *decompressed = malloc( - sizeof *decompressed * MAX_SERVER_TO_CLIENT); // @Robust no malloc + unsigned char *decompressed = malloc(sizeof *decompressed * MAX_SERVER_TO_CLIENT); // @Robust no malloc size_t decompressed_max_len = MAX_SERVER_TO_CLIENT; flight_assert(LZO1X_MEM_DECOMPRESS == 0); @@ -1987,7 +2049,7 @@ static void frame(void) { if (p->alive) { - p->alive_for += dt; + p->alive_for += dt*1.5; p->pos = cpvadd(p->pos, cpvmult(p->vel, dt)); if (p->alive_for > 1.0) { @@ -2082,6 +2144,54 @@ static void frame(void) // drawing PROFILE_SCOPE("drawing") { + + // draw particles in separate buffer so shader can operate on the buffer as a whole + PROFILE_SCOPE("drawing particles") + { + sgp_begin((int)width, (int)height); + sgp_viewport(0, 0, (int)width, (int)height); + sgp_project(0.0f, (float)width, 0.0f, (float)height); + sgp_set_blend_mode(SGP_BLENDMODE_BLEND); + + set_color_values(1.0, 1.0, 1.0, 0.0); + sgp_clear(); + + // actually draw them + transform_scope() + { + transform_worldspace_zoom(width, height); + transform_worldspace_camera(); + set_color(WHITE); + + PARTICLES_ITER(p) + { + if (p->alive) + { + // Color birth_col = colhexcode(0xc32c69); + // Color death_col = colhexcode(0xeca274); + + // Color col = Collerp(birth_col, death_col, p->alive_for); + // set_color_values(col.r, col.g, col.b, 1.0 - clamp01(p->alive_for)); + set_color_values(1.0, 1.0, 1.0, 1.0 - clamp01(p->alive_for)); + // pipeline_scope(goodpixel_pipeline) + { + sgp_set_image(0, image_pip); + draw_texture_centered(p->pos, 0.2 * p->scaling); + sgp_reset_image(0); + } + } + } + } + + sg_pass_action pass_action = {0}; + sg_begin_pass(fire_pass, &pass_action); + // sg_begin_default_pass(&pass_action, (int)width, (int)height); + sgp_flush(); + sgp_end(); + sg_end_pass(); + sg_commit(); + } + sgp_begin((int)width, (int)height); sgp_viewport(0, 0, (int)width, (int)height); sgp_project(0.0f, (float)width, 0.0f, (float)height); @@ -2089,16 +2199,14 @@ static void frame(void) // Draw background color set_color(colhexcode(0x000000)); - // set_color_values(0.1, 0.1, 0.1, 1.0); sgp_clear(); - // WORLD SPACE - // world space coordinates are +Y up, -Y down. Like normal cartesian coords + draw_circle(cpv(10, 10), 100); + + // draw background stuff transform_scope() { - translate(width / 2, height / 2); - scale_at(zoom, -zoom, 0.0, 0.0); - + transform_worldspace_zoom(width, height); // parllax layers, just the zooming, but not 100% of the camera panning #if 1 // space background transform_scope() @@ -2153,10 +2261,27 @@ static void frame(void) draw_dots(scaled_camera_pos, 2.0); } #endif + } - // camera go to player - translate(-camera_pos.x, -camera_pos.y); + // draw particles pass in screen space +#if 1 // whether to apply fire shader to the buffer + pipeline_scope(fire_pipeline) +#endif + { + sgp_set_image(0, fire_rendertarget); + set_color(WHITE); + sgp_draw_textured_rect(0.0f, 0.0f, (float)width, (float)height); + sgp_reset_image(0); + } + + // WORLD SPACE + // world space coordinates are +Y up, -Y down. Like normal cartesian coords + transform_scope() + { + transform_worldspace_zoom(width, height); + // camera go to player + transform_worldspace_camera(); draw_dots(camera_pos, 1.5); // in plane dots // hand reached limit circle @@ -2206,22 +2331,6 @@ static void frame(void) player_scaling = lerp(player_scaling, player_scaling_target, dt * 15.0); hovering_this_player = (EntityID){0}; - // draw particles drawn in world space - set_color(WHITE); - PARTICLES_ITER(p) - { - if (p->alive) - { - set_color_values(1.0, 1.0, 1.0, 1.0 - clamp01(p->alive_for)); - pipeline_scope(goodpixel_pipeline) - { - sgp_set_image(0, image_pip); - draw_texture_centered(p->pos, 0.2 * p->scaling); - sgp_reset_image(0); - } - } - } - // draw all types of entities ENTITIES_ITER(e) { @@ -2249,15 +2358,16 @@ static void frame(void) if (b->box_type == BoxThruster) { // spawn particles - if(b->thrust > 0.0) + if (b->thrust > 0.0) { cpVect particle_vel = box_vel(b); - double hash_offset = (double)get_id(&gs,b).index; // to make each thruster have a unique pattern of exhaust + double hash_offset = (double)get_id(&gs, b).index; // to make each thruster have a unique pattern of exhaust cpVect additional_vel = cpvmult(box_facing_vector(b), 0.5 + hash11(exec_time + hash_offset) * 0.2); // move outwards from thruster additional_vel = cpvspin(additional_vel, hash11(exec_time + hash_offset) * 0.1); // some spin particle_vel = cpvadd(particle_vel, additional_vel); new_particle(cpvadd(entity_pos(b), cpvmult(box_facing_vector(b), BOX_SIZE * 0.5)), particle_vel); } + /* transform_scope() { set_color_values(1.0, 1.0, 1.0, 1.0); @@ -2270,6 +2380,7 @@ static void frame(void) } sgp_reset_image(0); } + */ } sg_image img = boxinfo(b->box_type).image; if (b->box_type == BoxCockpit) diff --git a/shadergen.bat b/shadergen.bat index a4812d9..9e89135 100644 --- a/shadergen.bat +++ b/shadergen.bat @@ -7,4 +7,5 @@ IF %ERRORLEVEL% NEQ 0 ECHO ERROR download sokol-shdc from https://github.com/flo sokol-shdc.exe --format sokol --input hueshift.glsl --output hueshift.gen.h --slang glsl330:hlsl5:metal_macos sokol-shdc.exe --format sokol --input lightning.glsl --output lightning.gen.h --slang glsl330:hlsl5:metal_macos sokol-shdc.exe --format sokol --input horizontal_lightning.glsl --output horizontal_lightning.gen.h --slang glsl330:hlsl5:metal_macos -sokol-shdc.exe --format sokol --input goodpixel.glsl --output goodpixel.gen.h --slang glsl330:hlsl5:metal_macos \ No newline at end of file +sokol-shdc.exe --format sokol --input goodpixel.glsl --output goodpixel.gen.h --slang glsl330:hlsl5:metal_macos +sokol-shdc.exe --format sokol --input fire.glsl --output fire.gen.h --slang glsl330:hlsl5:metal_macos \ No newline at end of file