Get shadows for armatures working, testing shadow pillar

main
parent 782e263e54
commit 6d3594c6ad

BIN
art/art.blend (Stored with Git LFS)

Binary file not shown.

336
main.c

@ -2750,6 +2750,8 @@ typedef struct {
sg_pipeline pip; sg_pipeline pip;
sg_image color_img; sg_image color_img;
sg_image depth_img; sg_image depth_img;
sg_pipeline armature_pip;
} Shadow_State; } Shadow_State;
Shadow_State init_shadow_state(); Shadow_State init_shadow_state();
@ -3319,8 +3321,6 @@ void init(void)
.label = "armature", .label = "armature",
}); });
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] = { .action = SG_ACTION_LOAD },
@ -3992,7 +3992,6 @@ void dbgplanerect(AABB aabb)
void draw_armature(Mat4 view, Mat4 projection, Transform t, Armature *armature) void draw_armature(Mat4 view, Mat4 projection, Transform t, Armature *armature)
{ {
MD_ArenaTemp scratch = MD_GetScratch(0, 0);
sg_apply_pipeline(state.armature_pip); sg_apply_pipeline(state.armature_pip);
Mat4 model = transform_to_matrix(t); Mat4 model = transform_to_matrix(t);
@ -4004,80 +4003,6 @@ void draw_armature(Mat4 view, Mat4 projection, Transform t, Armature *armature)
.bones_tex_size = V2((float)armature->bones_texture_width,(float)armature->bones_texture_height), .bones_tex_size = V2((float)armature->bones_texture_width,(float)armature->bones_texture_height),
}; };
int bones_tex_size = 4 * armature->bones_texture_width * armature->bones_texture_height;
MD_u8 *bones_tex = MD_ArenaPush(scratch.arena, bones_tex_size);
for(MD_u64 i = 0; i < armature->bones_length; i++)
{
Bone *cur = &armature->bones[i];
// for debug drawing
Vec3 from = MulM4V3(cur->matrix_local, V3(0,0,0));
Vec3 x = MulM4V3(cur->matrix_local, V3(cur->length,0,0));
Vec3 y = MulM4V3(cur->matrix_local, V3(0,cur->length,0));
Vec3 z = MulM4V3(cur->matrix_local, V3(0,0,cur->length));
Mat4 final = M4D(1.0f);
final = MulM4(cur->inverse_model_space_pos, final);
for(Bone *cur_in_hierarchy = cur; cur_in_hierarchy; cur_in_hierarchy = cur_in_hierarchy->parent)
{
//final = MulM4(cur_in_hierarchy->anim_poses[0].parent_space_pose, final);
int bone_index = (int)(cur_in_hierarchy - armature->bones);
//final = MulM4(get_animated_bone_transform(&armature->animations[0].tracks[bone_index], cur_in_hierarchy, elapsed_time), final);
final = MulM4(transform_to_matrix(armature->anim_blended_poses[bone_index]), final);
}
from = MulM4V3(final, from);
x = MulM4V3(final, x);
y = MulM4V3(final, y);
z = MulM4V3(final, z);
Mat4 transform_matrix = transform_to_matrix(t);
from = MulM4V3(transform_matrix, from);
x = MulM4V3(transform_matrix, x);
y = MulM4V3(transform_matrix, y);
z = MulM4V3(transform_matrix, z);
dbgcol(LIGHTBLUE)
dbgsquare3d(y);
dbgcol(RED)
dbg3dline(from, x);
dbgcol(GREEN)
dbg3dline(from, y);
dbgcol(BLUE)
dbg3dline(from, z);
for(int col = 0; col < 4; col++)
{
Vec4 to_upload = final.Columns[col];
int bytes_per_pixel = 4;
int bytes_per_column_of_mat = bytes_per_pixel * 4;
int bytes_per_row = bytes_per_pixel * armature->bones_texture_width;
for(int elem = 0; elem < 4; elem++)
{
float after_decoding = decode_normalized_float32(encode_normalized_float32(to_upload.Elements[elem]));
assert(fabsf(after_decoding - to_upload.Elements[elem]) < 0.01f);
}
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*0], encode_normalized_float32(to_upload.Elements[0]).rgba, bytes_per_pixel);
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*1], encode_normalized_float32(to_upload.Elements[1]).rgba, bytes_per_pixel);
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*2], encode_normalized_float32(to_upload.Elements[2]).rgba, bytes_per_pixel);
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*3], encode_normalized_float32(to_upload.Elements[3]).rgba, bytes_per_pixel);
}
}
sg_update_image(armature->bones_texture, &(sg_image_data){
.subimage[0][0] = (sg_range){bones_tex, bones_tex_size},
});
ARR_ITER(sg_image, state.threedee_bind.vs_images)
{
*it = (sg_image){0};
}
ARR_ITER(sg_image, state.threedee_bind.fs_images)
{
*it = (sg_image){0};
}
state.threedee_bind.vertex_buffers[0] = armature->loaded_buffer; state.threedee_bind.vertex_buffers[0] = armature->loaded_buffer;
state.threedee_bind.vs_images[SLOT_threedee_bones_tex] = armature->bones_texture; state.threedee_bind.vs_images[SLOT_threedee_bones_tex] = armature->bones_texture;
state.threedee_bind.fs_images[SLOT_threedee_tex] = armature->image; state.threedee_bind.fs_images[SLOT_threedee_tex] = armature->image;
@ -4090,7 +4015,6 @@ void draw_armature(Mat4 view, Mat4 projection, Transform t, Armature *armature)
num_vertices += (int)armature->vertices_length; num_vertices += (int)armature->vertices_length;
sg_draw(0, (int)armature->vertices_length, 1); sg_draw(0, (int)armature->vertices_length, 1);
MD_ReleaseScratch(scratch);
} }
typedef struct typedef struct
@ -4974,63 +4898,76 @@ Shadow_State init_shadow_state() {
Shadow_State shadows = {0}; Shadow_State shadows = {0};
shadows.pass_action = (sg_pass_action) { shadows.pass_action = (sg_pass_action) {
.colors[0] = { .colors[0] = {
.action = SG_ACTION_CLEAR, .action = SG_ACTION_CLEAR,
.value = { 1.0f, 1.0f, 1.0f, 1.0f } .value = { 1.0f, 1.0f, 1.0f, 1.0f }
} }
}; };
/* /*
As of right now, it looks like sokol_gfx does not support depth only As of right now, it looks like sokol_gfx does not support depth only
rendering passes, so we create the colour buffer always. It will likely rendering passes, so we create the colour buffer always. It will likely
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.
*/ */
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, .min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR, .mag_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_CLAMP_TO_BORDER, .wrap_u = SG_WRAP_CLAMP_TO_BORDER,
.wrap_v = SG_WRAP_CLAMP_TO_BORDER, .wrap_v = SG_WRAP_CLAMP_TO_BORDER,
.border_color = SG_BORDERCOLOR_OPAQUE_WHITE, .border_color = SG_BORDERCOLOR_OPAQUE_WHITE,
.sample_count = 1, .sample_count = 1,
.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);
img_desc.pixel_format = SG_PIXELFORMAT_DEPTH; img_desc.pixel_format = SG_PIXELFORMAT_DEPTH;
img_desc.label = "shadow-map-depth-image"; img_desc.label = "shadow-map-depth-image";
shadows.depth_img = sg_make_image(&img_desc); shadows.depth_img = sg_make_image(&img_desc);
shadows.pass = sg_make_pass(&(sg_pass_desc){ shadows.pass = sg_make_pass(&(sg_pass_desc){
.color_attachments[0].image = shadows.color_img, .color_attachments[0].image = shadows.color_img,
.depth_stencil_attachment.image = shadows.depth_img, .depth_stencil_attachment.image = shadows.depth_img,
.label = "shadow-map-pass" .label = "shadow-map-pass"
}); });
shadows.pip = sg_make_pipeline(&(sg_pipeline_desc){ sg_pipeline_desc desc = (sg_pipeline_desc){
.layout = { .layout = {
.attrs = { .attrs = {
[ATTR_threedee_vs_pos_in].format = SG_VERTEXFORMAT_FLOAT3, [ATTR_threedee_vs_pos_in].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_threedee_vs_uv_in].format = SG_VERTEXFORMAT_FLOAT2, [ATTR_threedee_vs_uv_in].format = SG_VERTEXFORMAT_FLOAT2,
} }
}, },
.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 = 1, .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,
.write_enabled = true, .write_enabled = true,
}, },
.colors[0].pixel_format = SG_PIXELFORMAT_RGBA8, .colors[0].pixel_format = SG_PIXELFORMAT_RGBA8,
.label = "shadow-map-pipeline" .label = "shadow-map-pipeline"
}); };
shadows.pip = sg_make_pipeline(&desc);
desc.label = "armature-shadow-map-pipeline";
desc.shader = sg_make_shader(threedee_armature_shadow_mapping_shader_desc(sg_query_backend()));
sg_vertex_attr_desc skeleton_vertex_attrs[] = {
[ATTR_threedee_vs_skeleton_pos_in].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_threedee_vs_skeleton_uv_in].format = SG_VERTEXFORMAT_FLOAT2,
[ATTR_threedee_vs_skeleton_indices_in].format = SG_VERTEXFORMAT_USHORT4N,
[ATTR_threedee_vs_skeleton_weights_in].format = SG_VERTEXFORMAT_FLOAT4,
};
assert(ARRLEN(skeleton_vertex_attrs) < ARRLEN(desc.layout.attrs));
memcpy(desc.layout.attrs, skeleton_vertex_attrs, sizeof(skeleton_vertex_attrs));
shadows.armature_pip = sg_make_pipeline(&desc);
return shadows; return shadows;
} }
@ -5338,6 +5275,82 @@ void frame(void)
// Draw all the 3D drawn things. Draw the shadows, then draw the things with the shadows. // Draw all the 3D drawn things. Draw the shadows, then draw the things with the shadows.
// Process armatures and upload their skeleton textures // Process armatures and upload their skeleton textures
{ {
// Animate armatures, and upload their bone textures. Also debug draw their skeleton
{
SLICE_ITER(DrawnThing, drawn_this_frame)
{
if(it->armature)
{
MD_ArenaTemp scratch = MD_GetScratch(0, 0);
Armature *armature = it->armature;
int bones_tex_size = 4 * armature->bones_texture_width * armature->bones_texture_height;
MD_u8 *bones_tex = MD_ArenaPush(scratch.arena, bones_tex_size);
for(MD_u64 i = 0; i < armature->bones_length; i++)
{
Bone *cur = &armature->bones[i];
// for debug drawing
Vec3 from = MulM4V3(cur->matrix_local, V3(0,0,0));
Vec3 x = MulM4V3(cur->matrix_local, V3(cur->length,0,0));
Vec3 y = MulM4V3(cur->matrix_local, V3(0,cur->length,0));
Vec3 z = MulM4V3(cur->matrix_local, V3(0,0,cur->length));
Mat4 final = M4D(1.0f);
final = MulM4(cur->inverse_model_space_pos, final);
for(Bone *cur_in_hierarchy = cur; cur_in_hierarchy; cur_in_hierarchy = cur_in_hierarchy->parent)
{
int bone_index = (int)(cur_in_hierarchy - armature->bones);
final = MulM4(transform_to_matrix(armature->anim_blended_poses[bone_index]), final);
}
from = MulM4V3(final, from);
x = MulM4V3(final, x);
y = MulM4V3(final, y);
z = MulM4V3(final, z);
Mat4 transform_matrix = transform_to_matrix(it->t);
from = MulM4V3(transform_matrix, from);
x = MulM4V3(transform_matrix, x);
y = MulM4V3(transform_matrix, y);
z = MulM4V3(transform_matrix, z);
dbgcol(LIGHTBLUE)
dbgsquare3d(y);
dbgcol(RED)
dbg3dline(from, x);
dbgcol(GREEN)
dbg3dline(from, y);
dbgcol(BLUE)
dbg3dline(from, z);
for(int col = 0; col < 4; col++)
{
Vec4 to_upload = final.Columns[col];
int bytes_per_pixel = 4;
int bytes_per_column_of_mat = bytes_per_pixel * 4;
int bytes_per_row = bytes_per_pixel * armature->bones_texture_width;
for(int elem = 0; elem < 4; elem++)
{
float after_decoding = decode_normalized_float32(encode_normalized_float32(to_upload.Elements[elem]));
assert(fabsf(after_decoding - to_upload.Elements[elem]) < 0.01f);
}
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*0], encode_normalized_float32(to_upload.Elements[0]).rgba, bytes_per_pixel);
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*1], encode_normalized_float32(to_upload.Elements[1]).rgba, bytes_per_pixel);
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*2], encode_normalized_float32(to_upload.Elements[2]).rgba, bytes_per_pixel);
memcpy(&bones_tex[bytes_per_column_of_mat*col + bytes_per_row*i + bytes_per_pixel*3], encode_normalized_float32(to_upload.Elements[3]).rgba, bytes_per_pixel);
}
}
sg_update_image(armature->bones_texture, &(sg_image_data){
.subimage[0][0] = (sg_range){bones_tex, bones_tex_size},
});
MD_ReleaseScratch(scratch);
}
}
}
// do the shadow pass // do the shadow pass
Mat4 light_space_matrix; Mat4 light_space_matrix;
{ {
@ -5347,6 +5360,8 @@ void frame(void)
light_space_matrix = MulM4(shadow_projection, shadow_view); light_space_matrix = MulM4(shadow_projection, shadow_view);
sg_begin_pass(state.shadows.pass, &state.shadows.pass_action); sg_begin_pass(state.shadows.pass, &state.shadows.pass_action);
// shadows for meshes
sg_apply_pipeline(state.shadows.pip); sg_apply_pipeline(state.shadows.pip);
SLICE_ITER(DrawnThing, drawn_this_frame) SLICE_ITER(DrawnThing, drawn_this_frame)
{ {
@ -5369,9 +5384,33 @@ void frame(void)
num_vertices += (int)it->mesh->num_vertices; num_vertices += (int)it->mesh->num_vertices;
sg_draw(0, (int)it->mesh->num_vertices, 1); sg_draw(0, (int)it->mesh->num_vertices, 1);
} }
}
// shadows for armatures
sg_apply_pipeline(state.shadows.armature_pip);
SLICE_ITER(DrawnThing, drawn_this_frame)
{
if(it->armature) if(it->armature)
{ {
// @TODO sg_bindings bindings = {0};
bindings.vs_images[SLOT_threedee_bones_tex] = it->armature->bones_texture;
bindings.fs_images[SLOT_threedee_tex] = it->armature->image;
bindings.vertex_buffers[0] = it->armature->loaded_buffer;
sg_apply_bindings(&bindings);
Mat4 model = transform_to_matrix(it->t);
threedee_skeleton_vs_params_t params = {
.model = model,
.view = shadow_view,
.projection = shadow_projection,
.directional_light_space_matrix = light_space_matrix,
.bones_tex_size = V2((float)it->armature->bones_texture_width,(float)it->armature->bones_texture_height),
};
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_threedee_skeleton_vs_params, &SG_RANGE(params));
num_draw_calls += 1;
num_vertices += (int)it->armature->vertices_length;
sg_draw(0, (int)it->armature->vertices_length, 1);
} }
} }
sg_end_pass(); sg_end_pass();
@ -5381,8 +5420,8 @@ void frame(void)
{ {
sg_begin_default_pass(&state.clear_everything_pass_action, sapp_width(), sapp_height()); sg_begin_default_pass(&state.clear_everything_pass_action, sapp_width(), sapp_height());
// draw meshes
sg_apply_pipeline(state.threedee_pip); sg_apply_pipeline(state.threedee_pip);
state.threedee_bind.fs_images[SLOT_threedee_shadow_map] = state.shadows.color_img;
SLICE_ITER(DrawnThing, drawn_this_frame) SLICE_ITER(DrawnThing, drawn_this_frame)
{ {
if(it->mesh) if(it->mesh)
@ -5410,12 +5449,47 @@ void frame(void)
sg_draw(0, (int)it->mesh->num_vertices, 1); sg_draw(0, (int)it->mesh->num_vertices, 1);
} }
}
// draw armatures armature rendering
sg_apply_pipeline(state.armature_pip);
SLICE_ITER(DrawnThing, drawn_this_frame)
{
if(it->armature) if(it->armature)
{ {
sg_bindings bindings = {0};
bindings.vs_images[SLOT_threedee_bones_tex] = it->armature->bones_texture;
bindings.fs_images[SLOT_threedee_tex] = it->armature->image;
bindings.fs_images[SLOT_threedee_shadow_map] = state.shadows.color_img;
bindings.vertex_buffers[0] = it->armature->loaded_buffer;
sg_apply_bindings(&bindings);
Mat4 model = transform_to_matrix(it->t);
threedee_skeleton_vs_params_t params = {
.model = model,
.view = view,
.projection = projection,
.directional_light_space_matrix = light_space_matrix,
.bones_tex_size = V2((float)it->armature->bones_texture_width,(float)it->armature->bones_texture_height),
};
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_threedee_skeleton_vs_params, &SG_RANGE(params));
threedee_fs_params_t fs_params = {0};
fs_params.shadow_map_dimension = SHADOW_MAP_DIMENSION;
sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_threedee_fs_params, &SG_RANGE(fs_params));
num_draw_calls += 1;
num_vertices += (int)it->armature->vertices_length;
sg_draw(0, (int)it->armature->vertices_length, 1);
} }
*it = (DrawnThing){0};
} }
// zero out everything
SLICE_ITER(DrawnThing, drawn_this_frame)
{
*it = (DrawnThing){0};
}
sg_end_pass(); sg_end_pass();
} }
drawn_this_frame_length = 0; drawn_this_frame_length = 0;

@ -186,7 +186,7 @@ float bilinear_shadow_sample(sampler2D shadowMap, vec2 uv, int texture_width, in
float calculate_shadow_factor(sampler2D shadowMap, vec4 light_space_fragment_position, float n_dot_l) { float calculate_shadow_factor(sampler2D 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;
if(projected_coords.z > 1.0) if(projected_coords.z > 1.0)
return shadow; return shadow;
@ -272,3 +272,4 @@ void main() {
@program mesh vs fs @program mesh vs fs
@program armature vs_skeleton fs @program armature vs_skeleton fs
@program mesh_shadow_mapping vs fs_shadow_mapping @program mesh_shadow_mapping vs fs_shadow_mapping
@program armature_shadow_mapping vs_skeleton fs_shadow_mapping

Loading…
Cancel
Save