implement shadows for billboards and animation system
This commit is contained in:
parent
cff9194721
commit
1667107e85
8
.ignore
Normal file
8
.ignore
Normal file
@ -0,0 +1,8 @@
|
||||
.DS_Store
|
||||
.build/
|
||||
dist/
|
||||
first
|
||||
sample_game/
|
||||
!game/
|
||||
packs/*
|
||||
first.dSYM/Contents
|
||||
12
src/main.jai
12
src/main.jai
@ -131,6 +131,8 @@ init_after_asset_pack :: () {
|
||||
|
||||
is_in_reflection_pass : bool = false;
|
||||
|
||||
delta_time_accumulator : float64 = 0;
|
||||
|
||||
frame :: () {
|
||||
check_and_handle_window_resize();
|
||||
delta_time = get_time() - last_frame_time;
|
||||
@ -149,7 +151,15 @@ frame :: () {
|
||||
dpis := state.dpi_scale;
|
||||
|
||||
#if OS != .WASM { tick_profiler(); }
|
||||
if !in_editor_view then game_tick();
|
||||
|
||||
delta_time_accumulator += delta_time;
|
||||
|
||||
if !in_editor_view {
|
||||
while delta_time_accumulator > (1.0/60.0) {
|
||||
game_tick(1.0/60.0);
|
||||
delta_time_accumulator -= (1.0/60.0);
|
||||
}
|
||||
}
|
||||
fonsClearState(state.fons);
|
||||
for event: Input.events_this_frame {
|
||||
GR.getrect_handle_event(event);
|
||||
|
||||
@ -1,5 +1,44 @@
|
||||
g_animations: Table(string, Animation);
|
||||
|
||||
Animation_Player :: struct {
|
||||
current_animation : *Animation;
|
||||
queued_animation : *Animation = null;
|
||||
current_frame : s32 = 0;
|
||||
frame_start : float64 = 0;
|
||||
}
|
||||
|
||||
animation_player_tick :: (player: *Animation_Player) {
|
||||
if player.current_animation == null then return;
|
||||
frame := player.current_animation.frames[player.current_frame];
|
||||
current_time := get_time();
|
||||
if cast(s32)((current_time - player.frame_start) * 1000) > frame.duration_ms {
|
||||
player.current_frame += 1;
|
||||
player.frame_start = current_time;
|
||||
if player.current_frame >= player.current_animation.frames.count {
|
||||
player.current_frame = 0;
|
||||
if player.queued_animation != null {
|
||||
player.current_animation = player.queued_animation;
|
||||
player.queued_animation = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
animation_draw :: (player: *Animation_Player, position: Vector3, flipX: bool = false, flipY: bool = false) {
|
||||
animation_player_tick(player);
|
||||
if player.current_animation == null then print("Trying to draw a null animation!!\n");
|
||||
create_billboard_rendering_task(position, player.current_animation, player.current_frame, flipX, flipY);
|
||||
}
|
||||
|
||||
animation_set :: (player: *Animation_Player, animation: string) {
|
||||
player.current_frame = 0;
|
||||
player.current_animation = table_find_pointer(*g_animations, animation);
|
||||
}
|
||||
|
||||
animation_is :: (player: *Animation_Player, animation: string) -> bool {
|
||||
return player.current_animation.name == animation;
|
||||
}
|
||||
|
||||
Frame :: struct {
|
||||
x: s32;
|
||||
y: s32;
|
||||
|
||||
@ -64,6 +64,11 @@ Render_Command_Update_Trixels :: struct {
|
||||
Render_Command_Draw_Billboard :: struct {
|
||||
#as using c : Render_Command;
|
||||
c.type = .DRAW_BILLBOARD;
|
||||
position : Vector3;
|
||||
animation : *Animation;
|
||||
frame : s32;
|
||||
flipX : bool;
|
||||
flipY : bool;
|
||||
}
|
||||
|
||||
Render_Command_Draw_Trixels :: struct {
|
||||
|
||||
@ -41,7 +41,8 @@ backend_handle_command :: (cmd: *Render_Command) {
|
||||
set_light_command := cast(*Render_Command_Set_Light)cmd;
|
||||
current_world_config = set_light_command.worldConfig;
|
||||
case .DRAW_BILLBOARD;
|
||||
backend_draw_billboard();
|
||||
command := cast(*Render_Command_Draw_Billboard)cmd;
|
||||
backend_draw_billboard(command.position, command.animation, command.frame, command.flipX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,11 +143,11 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
|
||||
if !in_shadowmap_pass {
|
||||
mvp = create_viewproj(*camera);
|
||||
} else {
|
||||
mvp = create_shadow_viewproj(*camera, worldConf);
|
||||
shadow_mvp = mvp;
|
||||
mvp = shadow_mvp;
|
||||
}
|
||||
vs_params : Trile_Vs_Params;
|
||||
vs_params.mvp = mvp.floats;
|
||||
vs_params.mvp_shadow = shadow_mvp.floats;
|
||||
vs_params.camera = camera.position.component;
|
||||
sg_apply_pipeline(gPipelines.trile.pipeline);
|
||||
world_conf : Trile_World_Config;
|
||||
@ -165,6 +166,8 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
|
||||
bindings.samplers[0] = gPipelines.trile.bind.samplers[0];
|
||||
bindings.images[0] = trilegfx.trixel_colors;
|
||||
bindings.images[1] = g_ssaobuf;
|
||||
bindings.samplers[2] = g_shadowmap_sampler;
|
||||
bindings.images[2] = g_shadowmap;
|
||||
|
||||
fs_params : Trile_Fs_Params;
|
||||
fs_params.mvp_shadow = shadow_mvp.floats;
|
||||
@ -225,25 +228,30 @@ backend_draw_ground :: (wc: *World_Config) {
|
||||
sg_draw(0, 6, 2);
|
||||
}
|
||||
|
||||
backend_draw_billboard :: () {
|
||||
backend_draw_billboard :: (position: Vector3, anim: *Animation, frame_idx: s32, flipX: bool) {
|
||||
if !anim then return;
|
||||
mvp := create_viewproj(*camera);
|
||||
vs_params : Billboard_Vs_Params;
|
||||
anim := table_find_pointer(*g_animations, "player_idle");
|
||||
if anim {
|
||||
gPipelines.billboard.bind.images[0] = anim.sheet;
|
||||
num := cast(s32)(get_time() / 0.1) % anim.frames.count;
|
||||
frame := anim.frames[num];
|
||||
vs_params.uvs = Vector4.{
|
||||
cast(float) frame.x / cast(float)anim.sheet_w,
|
||||
cast(float) frame.y / cast(float)anim.sheet_h,
|
||||
cast(float) frame.w / cast(float)anim.sheet_w,
|
||||
cast(float) frame.h / cast(float)anim.sheet_h,
|
||||
}.component;
|
||||
vs_params.size = Vector2.{cast(float)(frame.w / 16), cast(float)(frame.h / 16)}.component;
|
||||
vs_params.cam = camera.position.component;
|
||||
gPipelines.billboard.bind.images[0] = anim.sheet;
|
||||
frame := anim.frames[frame_idx];
|
||||
vs_params.uvs = Vector4.{
|
||||
cast(float) frame.x / cast(float)anim.sheet_w,
|
||||
cast(float) frame.y / cast(float)anim.sheet_h,
|
||||
cast(float) frame.w / cast(float)anim.sheet_w,
|
||||
cast(float) frame.h / cast(float)anim.sheet_h,
|
||||
}.component;
|
||||
if flipX {
|
||||
vs_params.uvs[0] += vs_params.uvs[2];
|
||||
vs_params.uvs[2] *= -1.0;
|
||||
}
|
||||
vs_params.mvp = mvp.floats;
|
||||
vs_params.offset = Vector3.{10, 1, 5.5}.component;
|
||||
vs_params.size = Vector2.{cast(float)(frame.w / 16), cast(float)(frame.h / 16)}.component;
|
||||
vs_params.cam = camera.position.component;
|
||||
if !in_shadowmap_pass {
|
||||
vs_params.mvp = mvp.floats;
|
||||
} else {
|
||||
vs_params.mvp = shadow_mvp.floats;
|
||||
}
|
||||
vs_params.offset = position.component;
|
||||
sg_apply_pipeline(gPipelines.billboard.pipeline);
|
||||
sg_apply_bindings(*gPipelines.billboard.bind);
|
||||
sg_apply_uniforms(UB_billboard_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
|
||||
@ -279,6 +287,7 @@ backend_process_command_buckets :: () {
|
||||
|
||||
// 2. Shadow pass
|
||||
if current_world_config != null {
|
||||
shadow_mvp = create_shadow_viewproj(*camera, current_world_config);
|
||||
in_shadowmap_pass = true;
|
||||
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, attachments = g_shadowmap_attachments}));
|
||||
for render_command_buckets.shadow {
|
||||
|
||||
@ -15,7 +15,6 @@ fill_uniform_with_engine_data :: (uniform: *$A, enginedata: *$B) {
|
||||
create_world_rendering_tasks :: (world: *World) {
|
||||
create_sky_rendering_task(*world.conf);
|
||||
create_set_light_rendering_task(*world.conf);
|
||||
create_billboard_rendering_task();
|
||||
for world.positions {
|
||||
if it.positions.count < 1 then continue;
|
||||
triletask := Rendering_Task_Trile.{};
|
||||
@ -48,8 +47,8 @@ create_ground_rendering_task :: (world: *World) {
|
||||
add_rendering_task(groundtask);
|
||||
}
|
||||
|
||||
create_billboard_rendering_task :: () {
|
||||
billboardtask := Rendering_Task_Billboard.{type = .BILLBOARD };
|
||||
create_billboard_rendering_task :: (position: Vector3, animation: *Animation, frame: s32, flipX: bool, flipY: bool) {
|
||||
billboardtask := Rendering_Task_Billboard.{type = .BILLBOARD, position = position, animation = animation, frame = frame, flipX = flipX, flipY = flipY };
|
||||
add_rendering_task(billboardtask);
|
||||
}
|
||||
|
||||
|
||||
@ -71,11 +71,10 @@ create_shadow_viewproj :: (cam: *Camera, conf: *World_Config) -> Matrix4 {
|
||||
max_v.y = max(max_v.y, transformed_corner.y);
|
||||
max_v.z = max(max_v.z, transformed_corner.z);
|
||||
}
|
||||
transformed_avg := (view * Vector4.{avg.x, avg.y, avg.z, 1.0}).xyz;
|
||||
max_v.xy = transformed_avg.xy + Vector2.{50, 50};
|
||||
min_v.xy = transformed_avg.xy - Vector2.{50, 50};
|
||||
max_v.xy = avg.xy + Vector2.{50, 50};
|
||||
min_v.xy = avg.xy - Vector2.{50, 50};
|
||||
|
||||
proj := matrix_ortho(min_v.x, max_v.x, min_v.y, max_v.y, -min_v.z, -max_v.z-100);
|
||||
proj := matrix_ortho(min_v.x, max_v.x, min_v.y, max_v.y, -max_v.z-100, -min_v.z);
|
||||
return view*proj;
|
||||
}
|
||||
|
||||
|
||||
@ -42,6 +42,11 @@ Rendering_Task_Ground :: struct {
|
||||
Rendering_Task_Billboard :: struct {
|
||||
#as using t : Rendering_Task;
|
||||
t.type = .BILLBOARD;
|
||||
position : Vector3;
|
||||
animation : *Animation;
|
||||
frame : s32;
|
||||
flipX : bool;
|
||||
flipY : bool;
|
||||
}
|
||||
|
||||
Rendering_Task_Trile :: struct {
|
||||
@ -121,8 +126,16 @@ tasks_to_commands :: () {
|
||||
array_add(*render_command_buckets.main, commandDrawGround);
|
||||
array_add(*render_command_buckets.gbuffer, commandDrawGround);
|
||||
case .BILLBOARD;
|
||||
billboardTask := (cast(*Rendering_Task_Billboard)it);
|
||||
commandDrawBillboard := New(Render_Command_Draw_Billboard,, temp);
|
||||
commandDrawBillboard.position = billboardTask.position;
|
||||
commandDrawBillboard.frame = billboardTask.frame;
|
||||
commandDrawBillboard.flipX = billboardTask.flipX;
|
||||
commandDrawBillboard.flipY = billboardTask.flipY;
|
||||
commandDrawBillboard.animation = billboardTask.animation;
|
||||
array_add(*render_command_buckets.main, commandDrawBillboard);
|
||||
array_add(*render_command_buckets.shadow, commandDrawBillboard);
|
||||
array_add(*render_command_buckets.reflection, commandDrawBillboard);
|
||||
case .SET_CAMERA;
|
||||
task := (cast(*Rendering_Task_Set_Camera)it);
|
||||
command := New(Render_Command_Set_Camera,, temp);
|
||||
|
||||
@ -122,7 +122,7 @@ vs_billboard_source_glsl430 := u8.[
|
||||
{
|
||||
discard;
|
||||
}
|
||||
color = vec4(_35.xyz * 0.300000011920928955078125, 1.0);
|
||||
color = vec4(_35.xyz * 0.5, 1.0);
|
||||
}
|
||||
|
||||
*/
|
||||
@ -149,9 +149,8 @@ fs_billboard_source_glsl430 := u8.[
|
||||
0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x73,
|
||||
0x63,0x61,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
|
||||
0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x5f,0x33,0x35,
|
||||
0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x33,0x30,0x30,0x30,0x30,0x30,0x30,
|
||||
0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,0x30,0x37,0x38,0x31,0x32,
|
||||
0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,
|
||||
0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
];
|
||||
/*
|
||||
#version 300 es
|
||||
@ -235,7 +234,7 @@ vs_billboard_source_glsl300es := u8.[
|
||||
{
|
||||
discard;
|
||||
}
|
||||
color = vec4(_35.xyz * 0.300000011920928955078125, 1.0);
|
||||
color = vec4(_35.xyz * 0.5, 1.0);
|
||||
}
|
||||
|
||||
*/
|
||||
@ -264,10 +263,8 @@ fs_billboard_source_glsl300es := u8.[
|
||||
0x32,0x35,0x29,0x0a,0x20,0x20,0x20,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
|
||||
0x20,0x20,0x64,0x69,0x73,0x63,0x61,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,
|
||||
0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,
|
||||
0x34,0x28,0x5f,0x33,0x35,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x33,0x30,
|
||||
0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,
|
||||
0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,
|
||||
0x0a,0x00,
|
||||
0x34,0x28,0x5f,0x33,0x35,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,0x2c,
|
||||
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
];
|
||||
/*
|
||||
#include <metal_stdlib>
|
||||
@ -387,7 +384,7 @@ vs_billboard_source_metal_macos := u8.[
|
||||
{
|
||||
discard_fragment();
|
||||
}
|
||||
out.color = float4(_27.xyz * 0.300000011920928955078125, 1.0);
|
||||
out.color = float4(_27.xyz * 0.5, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -424,11 +421,9 @@ fs_billboard_source_metal_macos := u8.[
|
||||
0x20,0x64,0x69,0x73,0x63,0x61,0x72,0x64,0x5f,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,
|
||||
0x74,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x6f,
|
||||
0x75,0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,
|
||||
0x34,0x28,0x5f,0x32,0x37,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x33,0x30,
|
||||
0x30,0x30,0x30,0x30,0x30,0x31,0x31,0x39,0x32,0x30,0x39,0x32,0x38,0x39,0x35,0x35,
|
||||
0x30,0x37,0x38,0x31,0x32,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,
|
||||
0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,
|
||||
0x0a,0x00,
|
||||
0x34,0x28,0x5f,0x32,0x37,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,0x2c,
|
||||
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
|
||||
0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||
];
|
||||
billboard_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
|
||||
desc: sg_shader_desc;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@ void main() {
|
||||
#endif
|
||||
vec4 sampled = texture(sampler2D(sprite, spritesmp), uv);
|
||||
if(sampled.a < 0.01) discard;
|
||||
color = vec4(sampled.rgb * 0.3, 1.0);
|
||||
color = vec4(sampled.rgb * 0.5, 1.0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -7,6 +7,7 @@ in vec4 instance;
|
||||
|
||||
layout(binding=0) uniform trile_vs_params {
|
||||
mat4 mvp;
|
||||
mat4 mvp_shadow;
|
||||
vec3 camera;
|
||||
};
|
||||
|
||||
@ -15,9 +16,11 @@ out vec3 to_center;
|
||||
out vec3 vpos; // The actual position;
|
||||
out vec3 ipos; // Trile space position;
|
||||
out vec4 fnormal;
|
||||
out vec4 light_proj_pos;
|
||||
|
||||
void main() {
|
||||
gl_Position = mvp * vec4(position.xyz + instance.xyz, 1.0);
|
||||
light_proj_pos = mvp_shadow * vec4(position.xyz + instance.xyz, 1.0);
|
||||
fnormal = normal;
|
||||
to_center = centre.xyz - position.xyz;
|
||||
vpos = position.xyz + instance.xyz;
|
||||
@ -54,6 +57,7 @@ in vec3 to_center;
|
||||
in vec3 vpos;
|
||||
in vec3 ipos;
|
||||
in vec4 fnormal;
|
||||
in vec4 light_proj_pos;
|
||||
out vec4 frag_color;
|
||||
|
||||
layout(binding=3) uniform trile_fs_params {
|
||||
@ -67,6 +71,8 @@ layout(binding = 0) uniform texture2D triletex;
|
||||
layout(binding = 0) uniform sampler trilesmp;
|
||||
layout(binding = 1) uniform texture2D ssaotex;
|
||||
layout(binding = 1) uniform sampler ssaosmp;
|
||||
layout(binding = 2) uniform texture2D shadowtex;
|
||||
layout(binding = 2) uniform sampler shadowsmp;
|
||||
|
||||
const float PI = 3.1412854;
|
||||
|
||||
@ -233,7 +239,12 @@ void main() {
|
||||
vec3 kD = vec3(1.0) - F;
|
||||
kD *= 1.0 - metallic;
|
||||
|
||||
light += (kD * albedo / PI + specular) * NdotL * sunLightColor * sunIntensity;
|
||||
vec3 light_pos = light_proj_pos.xyz / light_proj_pos.w;
|
||||
light_pos = light_pos * 0.5 + 0.5;
|
||||
light_pos.z -= 0.0005;
|
||||
float shadowp = texture(sampler2DShadow(shadowtex, shadowsmp), light_pos);
|
||||
|
||||
light += shadowp * (kD * albedo / PI + specular) * NdotL * sunLightColor * sunIntensity;
|
||||
|
||||
vec3 R = reflect(-V, N);
|
||||
vec3 modifier = vec3(1.0);
|
||||
@ -244,6 +255,7 @@ void main() {
|
||||
vec3 samp = sky(R, sunPosition);
|
||||
// light += F * samp * modifier;
|
||||
|
||||
|
||||
frag_color = vec4(mix(deepColor, light, smoothstep(0.0, planeHeight, vpos.y)), 1.0);
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user