WebGL2; update sokol; Web MSAA; AA Outlines

main
Phillip Trudeau-Tavara 9 months ago
parent 12965a7818
commit 75345ae684

2
.gitignore vendored

@ -109,3 +109,5 @@ modules.order
Module.symvers Module.symvers
Mkfile.old Mkfile.old
dkms.conf dkms.conf
emsdk/

@ -15,6 +15,7 @@ copy marketing_page\favicon.ico %OUTPUT_FOLDER%\favicon.ico
emcc ^ emcc ^
-sEXPORTED_FUNCTIONS=_main,_end_text_input,_stop_controlling_input,_start_controlling_input,_read_from_save_data,_dump_save_data,_is_receiving_text_input^ -sEXPORTED_FUNCTIONS=_main,_end_text_input,_stop_controlling_input,_start_controlling_input,_read_from_save_data,_dump_save_data,_is_receiving_text_input^
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap^ -sEXPORTED_RUNTIME_METHODS=ccall,cwrap^
-s USE_WEBGL2=1^
-s INITIAL_MEMORY=62914560^ -s INITIAL_MEMORY=62914560^
-s ALLOW_MEMORY_GROWTH -s TOTAL_STACK=15728640^ -s ALLOW_MEMORY_GROWTH -s TOTAL_STACK=15728640^
%FLAGS%^ %FLAGS%^

174
main.c

@ -26,8 +26,8 @@
#if defined(__EMSCRIPTEN__) #if defined(__EMSCRIPTEN__)
#define WEB #define WEB
#define SOKOL_GLES2 #define SOKOL_GLES3
#define SAMPLE_COUNT 1 // bumping this back to 4 is troublesome for web, because there's a mismatch in sample counts. Perhaps we must upgrade to gles3, in doing so, we should upgrade to the newest sokol gfx. #define SAMPLE_COUNT 4
#endif #endif
#define DRWAV_ASSERT game_assert #define DRWAV_ASSERT game_assert
@ -58,11 +58,7 @@ __declspec(dllexport) uint32_t AmdPowerXpressRequestHighPerformance = 0x00000001
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4191) // unsafe function calling #pragma warning(disable : 4191) // unsafe function calling
#ifdef WEB #ifdef WEB
# ifndef GL_EXT_PROTOTYPES # include <GLES3/gl3.h>
# define GL_GLEXT_PROTOTYPES
# endif
# include <GLES2/gl2.h>
# include <GLES2/gl2ext.h>
# undef glGetError # undef glGetError
# define glGetError() (GL_NO_ERROR) # define glGetError() (GL_NO_ERROR)
#endif #endif
@ -843,17 +839,14 @@ sg_image load_image(MD_String8 path)
.width = png_width, .width = png_width,
.height = png_height, .height = png_height,
.pixel_format = SG_PIXELFORMAT_RGBA8, .pixel_format = SG_PIXELFORMAT_RGBA8,
.min_filter = SG_FILTER_LINEAR,
.num_mipmaps = 1, .num_mipmaps = 1,
.wrap_u = SG_WRAP_CLAMP_TO_EDGE,
.wrap_v = SG_WRAP_CLAMP_TO_EDGE,
.mag_filter = SG_FILTER_LINEAR,
.data.subimage[0][0] = .data.subimage[0][0] =
{ {
.ptr = pixels, .ptr = pixels,
.size = (size_t)(png_width * png_height * num_channels), .size = (size_t)(png_width * png_height * num_channels),
} }
}); });
loaded->image = to_return; loaded->image = to_return;
MD_ReleaseScratch(scratch); MD_ReleaseScratch(scratch);
return to_return; return to_return;
@ -1232,14 +1225,6 @@ Armature load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armat
.width = to_return.bones_texture_width, .width = to_return.bones_texture_width,
.height = to_return.bones_texture_height, .height = to_return.bones_texture_height,
.pixel_format = SG_PIXELFORMAT_RGBA8, .pixel_format = SG_PIXELFORMAT_RGBA8,
.min_filter = SG_FILTER_NEAREST,
.mag_filter = SG_FILTER_NEAREST,
// for webgl NPOT texures https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
.wrap_u = SG_WRAP_CLAMP_TO_EDGE,
.wrap_v = SG_WRAP_CLAMP_TO_EDGE,
.wrap_w = SG_WRAP_CLAMP_TO_EDGE,
.usage = SG_USAGE_STREAM, .usage = SG_USAGE_STREAM,
}); });
@ -2670,17 +2655,23 @@ static struct
sg_bindings threedee_bind; sg_bindings threedee_bind;
sg_image outline_pass_image; sg_image outline_pass_image;
sg_image outline_pass_resolve_image;
sg_pass outline_pass; sg_pass outline_pass;
sg_pipeline outline_mesh_pip; sg_pipeline outline_mesh_pip;
sg_pipeline outline_armature_pip; sg_pipeline outline_armature_pip;
sg_pass threedee_pass; // is a pass so I can do post processing in a shader sg_pass threedee_pass; // is a pass so I can do post processing in a shader
sg_image threedee_pass_image; sg_image threedee_pass_image;
sg_image threedee_pass_resolve_image;
sg_image threedee_pass_depth_image; sg_image threedee_pass_depth_image;
sg_pipeline twodee_outline_pip; sg_pipeline twodee_outline_pip;
sg_pipeline twodee_colorcorrect_pip; sg_pipeline twodee_colorcorrect_pip;
sg_sampler sampler_linear;
sg_sampler sampler_linear_border;
sg_sampler sampler_nearest;
Shadow_State shadows; Shadow_State shadows;
} state; } state;
@ -2695,7 +2686,9 @@ void create_screenspace_gfx_state()
MAYBE_DESTROY(state.threedee_pass, sg_destroy_pass); MAYBE_DESTROY(state.threedee_pass, sg_destroy_pass);
MAYBE_DESTROY(state.outline_pass_image, sg_destroy_image); MAYBE_DESTROY(state.outline_pass_image, sg_destroy_image);
MAYBE_DESTROY(state.outline_pass_resolve_image, sg_destroy_image);
MAYBE_DESTROY(state.threedee_pass_image, sg_destroy_image); MAYBE_DESTROY(state.threedee_pass_image, sg_destroy_image);
MAYBE_DESTROY(state.threedee_pass_resolve_image, sg_destroy_image);
MAYBE_DESTROY(state.threedee_pass_depth_image, sg_destroy_image); MAYBE_DESTROY(state.threedee_pass_depth_image, sg_destroy_image);
#undef MAYBE_DESTROY #undef MAYBE_DESTROY
@ -2766,34 +2759,40 @@ void create_screenspace_gfx_state()
.width = sapp_width(), .width = sapp_width(),
.height = sapp_height(), .height = sapp_height(),
.pixel_format = SG_PIXELFORMAT_RGBA8, .pixel_format = SG_PIXELFORMAT_RGBA8,
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_CLAMP_TO_BORDER,
.wrap_v = SG_WRAP_CLAMP_TO_BORDER,
.border_color = SG_BORDERCOLOR_OPAQUE_WHITE,
.sample_count = SAMPLE_COUNT,
.label = "outline-pass-render-target", .label = "outline-pass-render-target",
}; };
desc.sample_count = SAMPLE_COUNT;
state.outline_pass_image = sg_make_image(&desc); state.outline_pass_image = sg_make_image(&desc);
desc.sample_count = 1;
state.outline_pass_resolve_image = sg_make_image(&desc);
state.outline_pass = sg_make_pass(&(sg_pass_desc){ state.outline_pass = sg_make_pass(&(sg_pass_desc){
.color_attachments[0].image = state.outline_pass_image, .color_attachments[0].image = state.outline_pass_image,
.resolve_attachments[0].image = state.outline_pass_resolve_image,
.depth_stencil_attachment = { .depth_stencil_attachment = {
0 0
}, },
.label = "outline-pass", .label = "outline-pass",
}); });
desc.sample_count = SAMPLE_COUNT; desc.sample_count = 1;
desc.label = "threedee-pass-render-target"; desc.label = "threedee-pass-render-target";
desc.sample_count = SAMPLE_COUNT;
state.threedee_pass_image = sg_make_image(&desc); state.threedee_pass_image = sg_make_image(&desc);
desc.label = "threedee-pass-resolve-render-target";
desc.sample_count = 1;
state.threedee_pass_resolve_image = sg_make_image(&desc);
desc.label = "threedee-pass-depth-render-target"; desc.label = "threedee-pass-depth-render-target";
desc.pixel_format = sapp_depth_format(); desc.pixel_format = sapp_depth_format();
desc.sample_count = SAMPLE_COUNT;
state.threedee_pass_depth_image = sg_make_image(&desc); state.threedee_pass_depth_image = sg_make_image(&desc);
state.threedee_pass = sg_make_pass(&(sg_pass_desc){ state.threedee_pass = sg_make_pass(&(sg_pass_desc){
.color_attachments[0].image = state.threedee_pass_image, .color_attachments[0].image = state.threedee_pass_image,
.resolve_attachments[0].image = state.threedee_pass_resolve_image,
.depth_stencil_attachment = (sg_pass_attachment_desc){ .depth_stencil_attachment = (sg_pass_attachment_desc){
.image = state.threedee_pass_depth_image, .image = state.threedee_pass_depth_image,
.mip_level = 0, .mip_level = 0,
@ -3013,8 +3012,8 @@ Color blendalpha(Color c, float alpha)
// in pixels // in pixels
Vec2 img_size(sg_image img) Vec2 img_size(sg_image img)
{ {
sg_image_info info = sg_query_image_info(img); sg_image_desc desc = sg_query_image_desc(img);
return V2((float)info.width, (float)info.height); return V2((float)desc.width, (float)desc.height);
} }
#ifdef DEVTOOLS #ifdef DEVTOOLS
@ -3136,8 +3135,6 @@ LoadedFont load_font(MD_Arena *arena, MD_String8 font_filepath, float font_size)
.width = font_bitmap_width, .width = font_bitmap_width,
.height = font_bitmap_width, .height = font_bitmap_width,
.pixel_format = SG_PIXELFORMAT_RGBA8, .pixel_format = SG_PIXELFORMAT_RGBA8,
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
.data.subimage[0][0] = .data.subimage[0][0] =
{ {
.ptr = font_bitmap_rgba, .ptr = font_bitmap_rgba,
@ -3212,6 +3209,7 @@ void init(void)
sg_setup(&(sg_desc) { sg_setup(&(sg_desc) {
.context = sapp_sgcontext(), .context = sapp_sgcontext(),
.buffer_pool_size = 512, .buffer_pool_size = 512,
.logger.func = slog_func,
}); });
stm_setup(); stm_setup();
saudio_setup(&(saudio_desc) { saudio_setup(&(saudio_desc) {
@ -3380,6 +3378,7 @@ void init(void)
.compare = SG_COMPAREFUNC_LESS_EQUAL, .compare = SG_COMPAREFUNC_LESS_EQUAL,
.write_enabled = true, .write_enabled = true,
}, },
.sample_count = SAMPLE_COUNT,
.colors[0].blend = (sg_blend_state){ .colors[0].blend = (sg_blend_state){
// allow transparency // allow transparency
.enabled = true, .enabled = true,
@ -3405,6 +3404,7 @@ void init(void)
.compare = SG_COMPAREFUNC_LESS_EQUAL, .compare = SG_COMPAREFUNC_LESS_EQUAL,
.write_enabled = true .write_enabled = true
}, },
.sample_count = SAMPLE_COUNT,
.layout = { .layout = {
.attrs = .attrs =
{ {
@ -3428,11 +3428,42 @@ void init(void)
state.clear_depth_buffer_pass_action = (sg_pass_action) state.clear_depth_buffer_pass_action = (sg_pass_action)
{ {
.colors[0] = { .action = SG_ACTION_LOAD }, .colors[0] = { .load_action = SG_LOADACTION_LOAD },
.depth = { .action = SG_ACTION_CLEAR, .value = 1.0f }, .depth = { .load_action = SG_LOADACTION_CLEAR, .clear_value = 1.0f },
}; };
state.clear_everything_pass_action = state.clear_depth_buffer_pass_action; state.clear_everything_pass_action = state.clear_depth_buffer_pass_action;
state.clear_everything_pass_action.colors[0] = (sg_color_attachment_action){ .action = SG_ACTION_CLEAR, .value = { clearcol.r, clearcol.g, clearcol.b, 1.0f } }; state.clear_everything_pass_action.colors[0] = (sg_color_attachment_action){ .load_action = SG_LOADACTION_CLEAR, .clear_value = { clearcol.r, clearcol.g, clearcol.b, 1.0f } };
state.sampler_linear = sg_make_sampler(&(sg_sampler_desc) {
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
// .mipmap_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_CLAMP_TO_EDGE,
.wrap_v = SG_WRAP_CLAMP_TO_EDGE,
// .max_anisotropy = 16,
.label = "sampler-linear",
});
state.sampler_linear_border = sg_make_sampler(&(sg_sampler_desc) {
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_CLAMP_TO_BORDER,
.wrap_v = SG_WRAP_CLAMP_TO_BORDER,
.border_color = SG_BORDERCOLOR_OPAQUE_WHITE,
.label = "sampler-linear-border",
});
state.sampler_nearest = sg_make_sampler(&(sg_sampler_desc) {
.min_filter = SG_FILTER_NEAREST,
.mag_filter = SG_FILTER_NEAREST,
// for webgl NPOT texures https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
.wrap_u = SG_WRAP_CLAMP_TO_EDGE,
.wrap_v = SG_WRAP_CLAMP_TO_EDGE,
.wrap_w = SG_WRAP_CLAMP_TO_EDGE,
.label = "sampler-nearest",
});
} }
Vec2 screen_size() Vec2 screen_size()
@ -3723,7 +3754,8 @@ void flush_quad_batch()
state.bind.vertex_buffer_offsets[0] = sg_append_buffer(state.bind.vertex_buffers[0], &(sg_range) { cur_batch_data, cur_batch_data_index*sizeof(*cur_batch_data) }); state.bind.vertex_buffer_offsets[0] = sg_append_buffer(state.bind.vertex_buffers[0], &(sg_range) { cur_batch_data, cur_batch_data_index*sizeof(*cur_batch_data) });
state.bind.fs_images[SLOT_threedee_twodee_tex] = cur_batch_image; state.bind.fs.images[SLOT_threedee_twodee_tex] = cur_batch_image; // NOTE that this might get FUCKED if a custom pipeline is provided with more/less texture slots!!!
state.bind.fs.samplers[SLOT_threedee_fs_twodee_smp] = state.sampler_linear; // NOTE that this might get FUCKED if a custom pipeline is provided with more/less sampler slots!!!
sg_apply_bindings(&state.bind); sg_apply_bindings(&state.bind);
cur_batch_params.tex_size = img_size(cur_batch_image); cur_batch_params.tex_size = img_size(cur_batch_image);
sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_threedee_twodee_fs_params, &SG_RANGE(cur_batch_params)); sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_threedee_twodee_fs_params, &SG_RANGE(cur_batch_params));
@ -4827,8 +4859,8 @@ Shadow_State init_shadow_state() {
shadows.pass_action = (sg_pass_action) { shadows.pass_action = (sg_pass_action) {
.colors[0] = { .colors[0] = {
.action = SG_ACTION_CLEAR, .load_action = SG_LOADACTION_CLEAR,
.value = { 1.0f, 1.0f, 1.0f, 1.0f } .clear_value = { 1.0f, 1.0f, 1.0f, 1.0f }
} }
}; };
@ -4838,18 +4870,14 @@ Shadow_State init_shadow_state() {
be pertinent to just dig into sokol and add the functionality we want later, be pertinent to just dig into sokol and add the functionality we want later,
but as a first pass, we will just do as the romans do. I.e. have both a colour but as a first pass, we will just do as the romans do. I.e. have both a colour
and depth component. - Canada Day 2023. and depth component. - Canada Day 2023.
TODO: with GLES3, depth only rendering passes are now supported
*/ */
sg_image_desc img_desc = { sg_image_desc img_desc = {
.render_target = true, .render_target = true,
.width = SHADOW_MAP_DIMENSION, .width = SHADOW_MAP_DIMENSION,
.height = SHADOW_MAP_DIMENSION, .height = SHADOW_MAP_DIMENSION,
.pixel_format = SG_PIXELFORMAT_RGBA8, .pixel_format = SG_PIXELFORMAT_RGBA8,
.min_filter = SG_FILTER_LINEAR, .sample_count = 1,
.mag_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_CLAMP_TO_BORDER,
.wrap_v = SG_WRAP_CLAMP_TO_BORDER,
.border_color = SG_BORDERCOLOR_OPAQUE_WHITE,
.sample_count = SAMPLE_COUNT,
.label = "shadow-map-color-image" .label = "shadow-map-color-image"
}; };
shadows.color_img = sg_make_image(&img_desc); shadows.color_img = sg_make_image(&img_desc);
@ -4873,7 +4901,7 @@ Shadow_State init_shadow_state() {
.shader = sg_make_shader(threedee_mesh_shadow_mapping_shader_desc(sg_query_backend())), .shader = sg_make_shader(threedee_mesh_shadow_mapping_shader_desc(sg_query_backend())),
// Cull front faces in the shadow map pass // Cull front faces in the shadow map pass
// .cull_mode = SG_CULLMODE_BACK, // .cull_mode = SG_CULLMODE_BACK,
.sample_count = SAMPLE_COUNT, .sample_count = 1,
.depth = { .depth = {
.pixel_format = SG_PIXELFORMAT_DEPTH, .pixel_format = SG_PIXELFORMAT_DEPTH,
.compare = SG_COMPAREFUNC_LESS_EQUAL, .compare = SG_COMPAREFUNC_LESS_EQUAL,
@ -4887,7 +4915,7 @@ Shadow_State init_shadow_state() {
desc.label = "armature-shadow-map-pipeline"; desc.label = "armature-shadow-map-pipeline";
desc.shader = sg_make_shader(threedee_armature_shadow_mapping_shader_desc(sg_query_backend())); desc.shader = sg_make_shader(threedee_armature_shadow_mapping_shader_desc(sg_query_backend()));
sg_vertex_attr_desc skeleton_vertex_attrs[] = { sg_vertex_attr_state skeleton_vertex_attrs[] = {
[ATTR_threedee_vs_skeleton_pos_in].format = SG_VERTEXFORMAT_FLOAT3, [ATTR_threedee_vs_skeleton_pos_in].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_threedee_vs_skeleton_uv_in].format = SG_VERTEXFORMAT_FLOAT2, [ATTR_threedee_vs_skeleton_uv_in].format = SG_VERTEXFORMAT_FLOAT2,
[ATTR_threedee_vs_skeleton_indices_in].format = SG_VERTEXFORMAT_USHORT4N, [ATTR_threedee_vs_skeleton_indices_in].format = SG_VERTEXFORMAT_USHORT4N,
@ -5090,9 +5118,17 @@ void actually_draw_thing(DrawnThing *it, Mat4 light_space_matrix, bool for_outli
else else
sg_apply_pipeline(state.threedee_pip); sg_apply_pipeline(state.threedee_pip);
sg_bindings bindings = {0}; sg_bindings bindings = {0};
bindings.fs_images[SLOT_threedee_tex] = it->mesh->image; bindings.fs.images[SLOT_threedee_tex] = it->mesh->image;
if(!for_outline) if(for_outline)
bindings.fs_images[SLOT_threedee_shadow_map] = state.shadows.color_img; {
bindings.fs.samplers[SLOT_threedee_fs_outline_smp] = state.sampler_linear;
}
else
{
bindings.fs.images[SLOT_threedee_shadow_map] = state.shadows.color_img;
bindings.fs.samplers[SLOT_threedee_fs_shadow_smp] = state.sampler_linear_border;
bindings.fs.samplers[SLOT_threedee_fs_smp] = state.sampler_linear;
}
bindings.vertex_buffers[0] = it->mesh->loaded_buffer; bindings.vertex_buffers[0] = it->mesh->loaded_buffer;
sg_apply_bindings(&bindings); sg_apply_bindings(&bindings);
@ -5118,10 +5154,19 @@ void actually_draw_thing(DrawnThing *it, Mat4 light_space_matrix, bool for_outli
else else
sg_apply_pipeline(state.armature_pip); sg_apply_pipeline(state.armature_pip);
sg_bindings bindings = {0}; sg_bindings bindings = {0};
bindings.vs_images[SLOT_threedee_bones_tex] = it->armature->bones_texture; bindings.vs.images[SLOT_threedee_bones_tex] = it->armature->bones_texture;
bindings.fs_images[SLOT_threedee_tex] = it->armature->image; bindings.vs.samplers[SLOT_threedee_vs_skeleton_smp] = state.sampler_nearest;
if(!for_outline) bindings.fs.images[SLOT_threedee_tex] = it->armature->image;
bindings.fs_images[SLOT_threedee_shadow_map] = state.shadows.color_img; if(for_outline)
{
bindings.fs.samplers[SLOT_threedee_fs_outline_smp] = state.sampler_linear;
}
else
{
bindings.fs.images[SLOT_threedee_shadow_map] = state.shadows.color_img;
bindings.fs.samplers[SLOT_threedee_fs_shadow_smp] = state.sampler_linear_border;
bindings.fs.samplers[SLOT_threedee_fs_smp] = state.sampler_linear;
}
bindings.vertex_buffers[0] = it->armature->loaded_buffer; bindings.vertex_buffers[0] = it->armature->loaded_buffer;
sg_apply_bindings(&bindings); sg_apply_bindings(&bindings);
@ -5265,7 +5310,8 @@ void flush_all_drawn_things(Vec3 light_dir, Vec3 cam_pos, Vec3 cam_facing, Vec3
if(it->mesh) if(it->mesh)
{ {
sg_bindings bindings = {0}; sg_bindings bindings = {0};
bindings.fs_images[SLOT_threedee_tex] = it->mesh->image; bindings.fs.images[SLOT_threedee_tex] = it->mesh->image;
bindings.fs.samplers[SLOT_threedee_fs_shadow_mapping_smp] = state.sampler_linear;
bindings.vertex_buffers[0] = it->mesh->loaded_buffer; bindings.vertex_buffers[0] = it->mesh->loaded_buffer;
sg_apply_bindings(&bindings); sg_apply_bindings(&bindings);
@ -5290,8 +5336,10 @@ void flush_all_drawn_things(Vec3 light_dir, Vec3 cam_pos, Vec3 cam_facing, Vec3
if(it->armature) if(it->armature)
{ {
sg_bindings bindings = {0}; sg_bindings bindings = {0};
bindings.vs_images[SLOT_threedee_bones_tex] = it->armature->bones_texture; bindings.vs.images[SLOT_threedee_bones_tex] = it->armature->bones_texture;
bindings.fs_images[SLOT_threedee_tex] = it->armature->image; bindings.vs.samplers[SLOT_threedee_vs_skeleton_smp] = state.sampler_nearest;
bindings.fs.images[SLOT_threedee_tex] = it->armature->image;
bindings.fs.samplers[SLOT_threedee_fs_shadow_mapping_smp] = state.sampler_linear;
bindings.vertex_buffers[0] = it->armature->loaded_buffer; bindings.vertex_buffers[0] = it->armature->loaded_buffer;
sg_apply_bindings(&bindings); sg_apply_bindings(&bindings);
@ -5317,8 +5365,8 @@ void flush_all_drawn_things(Vec3 light_dir, Vec3 cam_pos, Vec3 cam_facing, Vec3
{ {
sg_begin_pass(state.outline_pass, &(sg_pass_action) { sg_begin_pass(state.outline_pass, &(sg_pass_action) {
.colors[0] = { .colors[0] = {
.action = SG_ACTION_CLEAR, .load_action = SG_LOADACTION_CLEAR,
.value = { 0.0f, 0.0f, 0.0f, 0.0f }, .clear_value = { 0.0f, 0.0f, 0.0f, 0.0f },
} }
}); });
@ -5674,8 +5722,8 @@ void frame(void)
flush_all_drawn_things(light_dir, cam_pos, facing, right); flush_all_drawn_things(light_dir, cam_pos, facing, right);
// draw the 3d render // draw the 3d render
draw_quad((DrawParams){quad_at(V2(0.0, screen_size().y), screen_size()), IMG(state.threedee_pass_image), WHITE, .layer = LAYER_WORLD, .custom_pipeline = state.twodee_colorcorrect_pip }); draw_quad((DrawParams){quad_at(V2(0.0, screen_size().y), screen_size()), IMG(state.threedee_pass_resolve_image), WHITE, .layer = LAYER_WORLD, .custom_pipeline = state.twodee_colorcorrect_pip });
draw_quad((DrawParams){quad_at(V2(0.0, screen_size().y), screen_size()), IMG(state.outline_pass_image), WHITE, .custom_pipeline = state.twodee_outline_pip, .layer = LAYER_UI}); draw_quad((DrawParams){quad_at(V2(0.0, screen_size().y), screen_size()), IMG(state.outline_pass_resolve_image), WHITE, .custom_pipeline = state.twodee_outline_pip, .layer = LAYER_UI});
// 2d drawing TODO move this to when the drawing is flushed. // 2d drawing TODO move this to when the drawing is flushed.
sg_begin_default_pass(&state.clear_depth_buffer_pass_action, sapp_width(), sapp_height()); sg_begin_default_pass(&state.clear_depth_buffer_pass_action, sapp_width(), sapp_height());
@ -6949,7 +6997,7 @@ ISANERROR("Don't know how to do this stuff on this platform.")
{ {
Vec2 depth_size = V2(200.0f, 200.0f); Vec2 depth_size = V2(200.0f, 200.0f);
draw_quad((DrawParams){quad_at(V2(screen_size().x - depth_size.x, screen_size().y), depth_size), IMG(state.shadows.color_img), WHITE, .layer = LAYER_UI_FG}); draw_quad((DrawParams){quad_at(V2(screen_size().x - depth_size.x, screen_size().y), depth_size), IMG(state.shadows.color_img), WHITE, .layer = LAYER_UI_FG});
draw_quad((DrawParams){quad_at(V2(0.0, screen_size().y/2.0f), MulV2F(screen_size(), 0.1f)), IMG(state.outline_pass_image), WHITE, .layer = LAYER_UI_FG}); draw_quad((DrawParams){quad_at(V2(0.0, screen_size().y/2.0f), MulV2F(screen_size(), 0.1f)), IMG(state.outline_pass_resolve_image), WHITE, .layer = LAYER_UI_FG});
Vec3 view_cam_pos = MulM4V4(InvGeneralM4(view), V4(0,0,0,1)).xyz; Vec3 view_cam_pos = MulM4V4(InvGeneralM4(view), V4(0,0,0,1)).xyz;
//if(view_cam_pos.y >= 4.900f) // causes nan if not true... not good... //if(view_cam_pos.y >= 4.900f) // causes nan if not true... not good...
@ -7110,10 +7158,10 @@ ISANERROR("Don't know how to do this stuff on this platform.")
}; };
// convert to uv space // convert to uv space
sg_image_info info = sg_query_image_info(d.image); sg_image_desc desc = sg_query_image_desc(d.image);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
tex_coords[i] = DivV2(tex_coords[i], V2((float)info.width, (float)info.height)); tex_coords[i] = DivV2(tex_coords[i], V2((float)desc.width, (float)desc.height));
} }
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
@ -7481,13 +7529,13 @@ sapp_desc sokol_main(int argc, char* argv[])
.frame_cb = frame, .frame_cb = frame,
.cleanup_cb = cleanup, .cleanup_cb = cleanup,
.event_cb = event, .event_cb = event,
.sample_count = SAMPLE_COUNT, .sample_count = 1,
.width = 800, .width = 800,
.height = 600, .height = 600,
//.gl_force_gles2 = true, not sure why this was here in example, look into
.window_title = "Dante's Cowboy", .window_title = "Dante's Cowboy",
.win32_console_attach = true, .win32_console_attach = true,
.win32_console_create = true, .win32_console_create = true,
.icon.sokol_default = true, .icon.sokol_default = true,
.logger.func = slog_func,
}; };
} }

@ -9,7 +9,7 @@ if exist gen\ (
) )
@REM shaders @REM shaders
thirdparty\sokol-shdc.exe --input threedee.glsl --output gen\threedee.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error thirdparty\sokol-shdc.exe --input threedee.glsl --output gen\threedee.glsl.h --slang glsl300es:hlsl5:glsl330 || goto :error
@REM metadesk codegen @REM metadesk codegen
cl /nologo /diagnostics:caret /Ithirdparty /W3 /Zi /WX codegen.c || goto :error cl /nologo /diagnostics:caret /Ithirdparty /W3 /Zi /WX codegen.c || goto :error

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -118,7 +118,6 @@ SOKOL_API_IMPL sg_context_desc sapp_sgcontext(void) {
desc.color_format = (sg_pixel_format) sapp_color_format(); desc.color_format = (sg_pixel_format) sapp_color_format();
desc.depth_format = (sg_pixel_format) sapp_depth_format(); desc.depth_format = (sg_pixel_format) sapp_depth_format();
desc.sample_count = sapp_sample_count(); desc.sample_count = sapp_sample_count();
desc.gl.force_gles2 = sapp_gles2();
desc.metal.device = sapp_metal_get_device(); desc.metal.device = sapp_metal_get_device();
desc.metal.renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor; desc.metal.renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor;
desc.metal.drawable_cb = sapp_metal_get_drawable; desc.metal.drawable_cb = sapp_metal_get_drawable;

@ -82,7 +82,8 @@ uniform skeleton_vs_params {
vec2 bones_tex_size; vec2 bones_tex_size;
}; };
uniform sampler2D bones_tex; uniform texture2D bones_tex;
uniform sampler vs_skeleton_smp;
float decode_normalized_float32(vec4 v) float decode_normalized_float32(vec4 v)
{ {
@ -110,7 +111,7 @@ void main() {
{ {
for(int col = 0; col < 4; col++) for(int col = 0; col < 4; col++)
{ {
bone_mat[col][row] = decode_normalized_float32(texture(bones_tex, vec2((0.5 + col*4 + row)/bones_tex_size.x, y_coord))); bone_mat[col][row] = decode_normalized_float32(texture(sampler2D(bones_tex, vs_skeleton_smp), vec2((0.5 + col*4 + row)/bones_tex_size.x, y_coord)));
} }
} }
@ -172,8 +173,10 @@ void main() {
@fs fs @fs fs
uniform sampler2D tex; uniform texture2D tex;
uniform sampler2D shadow_map; uniform texture2D shadow_map;
uniform sampler fs_smp;
uniform samplerShadow fs_shadow_smp;
uniform fs_params { uniform fs_params {
int shadow_map_dimension; int shadow_map_dimension;
@ -193,7 +196,7 @@ float decodeDepth(vec4 rgba) {
return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0)); return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
} }
float do_shadow_sample(sampler2D shadowMap, vec2 uv, float scene_depth, float n_dot_l) { float do_shadow_sample(texture2D shadowMap, vec2 uv, float scene_depth, float n_dot_l) {
{ {
//WebGL does not support GL_CLAMP_TO_BORDER, or border colors at all it seems, so we have to check explicitly. //WebGL does not support GL_CLAMP_TO_BORDER, or border colors at all it seems, so we have to check explicitly.
//This will probably slow down other versions which do support texture borders, but the current system does //This will probably slow down other versions which do support texture borders, but the current system does
@ -201,7 +204,7 @@ float do_shadow_sample(sampler2D shadowMap, vec2 uv, float scene_depth, float n_
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0)
return 1.0; return 1.0;
} }
float map_depth = decodeDepth(texture(shadowMap, uv)); float map_depth = decodeDepth(texture(sampler2D(shadowMap, fs_shadow_smp), uv));
// float bias = max(0.03f * (1.0f - n_dot_l), 0.005f); // float bias = max(0.03f * (1.0f - n_dot_l), 0.005f);
// bias = clamp(bias, 0.0, 0.01); // bias = clamp(bias, 0.0, 0.01);
@ -216,7 +219,7 @@ float do_shadow_sample(sampler2D shadowMap, vec2 uv, float scene_depth, float n_
} }
float bilinear_shadow_sample(sampler2D shadowMap, vec2 uv, int texture_width, int texture_height, float scene_depth_light_space, float n_dot_l) { float bilinear_shadow_sample(texture2D shadowMap, vec2 uv, int texture_width, int texture_height, float scene_depth_light_space, float n_dot_l) {
vec2 texture_dim = vec2(float(texture_width), float(texture_height)); vec2 texture_dim = vec2(float(texture_width), float(texture_height));
vec2 texel_dim = vec2(1.0 / float(texture_width ), 1.0 / float(texture_height)); vec2 texel_dim = vec2(1.0 / float(texture_width ), 1.0 / float(texture_height));
@ -244,7 +247,7 @@ float bilinear_shadow_sample(sampler2D shadowMap, vec2 uv, int texture_width, in
return result; return result;
} }
float calculate_shadow_factor(sampler2D shadowMap, vec4 light_space_fragment_position, float n_dot_l) { float calculate_shadow_factor(texture2D shadowMap, vec4 light_space_fragment_position, float n_dot_l) {
float shadow = 1.0; float shadow = 1.0;
vec3 projected_coords = light_space_fragment_position.xyz / light_space_fragment_position.w; vec3 projected_coords = light_space_fragment_position.xyz / light_space_fragment_position.w;
@ -275,7 +278,7 @@ float calculate_shadow_factor(sampler2D shadowMap, vec4 light_space_fragment_pos
} }
void main() { void main() {
vec4 col = texture(tex, uv); vec4 col = texture(sampler2D(tex, fs_smp), uv);
bool alpha_blend = bool(alpha_blend_int); bool alpha_blend = bool(alpha_blend_int);
@ -323,7 +326,8 @@ void main() {
@fs fs_shadow_mapping @fs fs_shadow_mapping
uniform sampler2D tex; uniform texture2D tex;
uniform sampler fs_shadow_mapping_smp;
in vec3 pos; in vec3 pos;
in vec2 uv; in vec2 uv;
@ -341,7 +345,7 @@ vec4 encodeDepth(float v) {
} }
void main() { void main() {
vec4 col = texture(tex, uv); vec4 col = texture(sampler2D(tex, fs_shadow_mapping_smp), uv);
if(col.a < 0.5) if(col.a < 0.5)
{ {
discard; discard;
@ -366,7 +370,9 @@ void main() {
@end @end
@fs fs_twodee @fs fs_twodee
uniform sampler2D twodee_tex; uniform texture2D twodee_tex;
uniform sampler fs_twodee_smp;
uniform twodee_fs_params { uniform twodee_fs_params {
vec4 tint; vec4 tint;
@ -387,7 +393,7 @@ out vec4 frag_color;
void main() { void main() {
// clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y // clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y
if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard; if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard;
frag_color = texture(twodee_tex, uv) * tint; frag_color = texture(sampler2D(twodee_tex, fs_twodee_smp), uv) * tint;
if(frag_color.a <= alpha_clip_threshold) if(frag_color.a <= alpha_clip_threshold)
{ {
discard; discard;
@ -397,7 +403,9 @@ void main() {
@end @end
@fs fs_twodee_outline @fs fs_twodee_outline
uniform sampler2D twodee_tex; uniform texture2D twodee_tex;
uniform sampler fs_twodee_outline_smp;
uniform twodee_fs_params { uniform twodee_fs_params {
vec4 tint; vec4 tint;
@ -419,30 +427,41 @@ void main() {
// clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y // clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y
if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard; if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard;
float left = texture(twodee_tex, uv + vec2(-1, 0)/tex_size).a; // 5-tap tent filter: centre, left, right, up, down
float right = texture(twodee_tex, uv + vec2(1, 0)/tex_size).a; float c = texture(sampler2D(twodee_tex, fs_twodee_outline_smp), uv).a;
float up = texture(twodee_tex, uv + vec2(0, 1)/tex_size).a; float l = texture(sampler2D(twodee_tex, fs_twodee_outline_smp), uv + vec2(-1, 0)/tex_size).a;
float down = texture(twodee_tex, uv + vec2(0, -1)/tex_size).a; float r = texture(sampler2D(twodee_tex, fs_twodee_outline_smp), uv + vec2(+1, 0)/tex_size).a;
float u = texture(sampler2D(twodee_tex, fs_twodee_outline_smp), uv + vec2(0, +1)/tex_size).a;
if( float d = texture(sampler2D(twodee_tex, fs_twodee_outline_smp), uv + vec2(0, -1)/tex_size).a;
false
|| left > 0.1 && right < 0.1 // if centre pixel is ~1, it is inside a shape.
|| left < 0.1 && right > 0.1 // if centre pixel is ~0, it is outside a shape.
|| up < 0.1 && down > 0.1 // if it is in the middle, it is near an MSAA-resolved edge.
|| up > 0.1 && down < 0.1 // we parallel-compute the inside AND outside glows, and then lerp using c.
) float lerp_t = c;
{
frag_color = vec4(1.0); // buffer is linear-space to be ACES-corrected later, but MSAA happens in gamma space;
} // I want a gamma-space blend; so I cheaply do pow(x, 2) by computing x*x.
else c *= c; l *= l; r *= r; u *= u; d *= d;
{
frag_color = vec4(0.0); float accum_o = (c + l + r + u + d);
} float accum_i = 5 - (c + l + r + u + d);
accum_o = 0.3 * accum_o;
accum_i = 0.3 * accum_i;
accum_o = clamp(accum_o, 0, 1);
accum_i = clamp(accum_i, 0, 1);
accum_o = sqrt(accum_o); // cheap gamma-undo
accum_i = sqrt(accum_i); // cheap gamma-undo
float accum = mix(accum_o, accum_i, lerp_t);
frag_color = vec4(1, 1, 1, accum);
} }
@end @end
@fs fs_twodee_color_correction @fs fs_twodee_color_correction
uniform sampler2D twodee_tex; uniform texture2D twodee_tex;
uniform sampler fs_twodee_color_correction_smp;
uniform twodee_fs_params { uniform twodee_fs_params {
vec4 tint; vec4 tint;
@ -473,7 +492,7 @@ void main() {
// clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y // clip space is from [-1,1] [left, right]of screen on X, and [-1,1] [bottom, top] of screen on Y
if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard; if(pos.x < clip_ul.x || pos.x > clip_lr.x || pos.y < clip_lr.y || pos.y > clip_ul.y) discard;
vec4 col = texture(twodee_tex, uv); vec4 col = texture(sampler2D(twodee_tex, fs_twodee_color_correction_smp), uv);
col.rgb = acesFilm(col.rgb); col.rgb = acesFilm(col.rgb);
@ -484,7 +503,8 @@ void main() {
@fs fs_outline @fs fs_outline
uniform sampler2D tex; uniform texture2D tex;
uniform sampler fs_outline_smp;
in vec3 pos; in vec3 pos;
in vec2 uv; in vec2 uv;
@ -495,7 +515,7 @@ in vec4 world_space_frag_pos;
out vec4 frag_color; out vec4 frag_color;
void main() { void main() {
vec4 col = texture(tex, uv); vec4 col = texture(sampler2D(tex, fs_outline_smp), uv);
if(col.a < 0.5) if(col.a < 0.5)
{ {
discard; discard;

Loading…
Cancel
Save