diff --git a/packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv b/packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv new file mode 100644 index 00000000..332dad05 Binary files /dev/null and b/packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/5e4589a1.vert.spv b/packages/ludic.render3d/shaders/spv/5e4589a1.vert.spv new file mode 100644 index 00000000..7051758f Binary files /dev/null and b/packages/ludic.render3d/shaders/spv/5e4589a1.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv b/packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv new file mode 100644 index 00000000..cbe9a3c4 Binary files /dev/null and b/packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/a0f2dbac.vert.spv b/packages/ludic.render3d/shaders/spv/a0f2dbac.vert.spv new file mode 100644 index 00000000..7051758f Binary files /dev/null and b/packages/ludic.render3d/shaders/spv/a0f2dbac.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/f2952361.frag.spv b/packages/ludic.render3d/shaders/spv/f2952361.frag.spv new file mode 100644 index 00000000..3ac120b3 Binary files /dev/null and b/packages/ludic.render3d/shaders/spv/f2952361.frag.spv differ diff --git a/packages/ludic.render3d/shaders/spv/f2952361.vert.spv b/packages/ludic.render3d/shaders/spv/f2952361.vert.spv new file mode 100644 index 00000000..7051758f Binary files /dev/null and b/packages/ludic.render3d/shaders/spv/f2952361.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/manifest.txt b/packages/ludic.render3d/shaders/spv/manifest.txt index 3d564e5d..cfa52ef1 100644 --- a/packages/ludic.render3d/shaders/spv/manifest.txt +++ b/packages/ludic.render3d/shaders/spv/manifest.txt @@ -2324,6 +2324,210 @@ T f4382918 u_snow_d 15 T f4382918 u_sunshadow 16 T f4382918 u_tershadow 17 T f4382918 u_ts_height 18 +P f2952361 terrain.vert terrain.frag #define SUN_INLINE; +B f2952361 vert 0 204 +U f2952361 vert u_half 0 float 1 0 +U f2952361 vert u_view 16 mat4 1 0 +U f2952361 vert u_proj 80 mat4 1 0 +U f2952361 vert u_origin 144 vec2 1 0 +U f2952361 vert u_cam_pos 160 vec3 1 0 +U f2952361 vert u_node 176 vec3 1 0 +U f2952361 vert u_morph 192 vec2 1 0 +U f2952361 vert u_grid 200 float 1 0 +I f2952361 a_xz 0 vec2 +B f2952361 frag 1 872 +U f2952361 frag u_cascade_vp 0 mat4 5 64 +U f2952361 frag u_cascade_split 320 float 5 16 +U f2952361 frag u_cascade_range 400 float 5 16 +U f2952361 frag u_cascade_texel 480 float 5 16 +U f2952361 frag u_sun_dir 560 vec3 1 0 +U f2952361 frag u_sun_color 576 vec3 1 0 +U f2952361 frag u_cam_pos 592 vec3 1 0 +U f2952361 frag u_prefilter_levels 604 float 1 0 +U f2952361 frag u_fog_density 608 float 1 0 +U f2952361 frag u_fog_height_falloff 612 float 1 0 +U f2952361 frag u_fog_base 616 float 1 0 +U f2952361 frag u_clip_y 620 float 1 0 +U f2952361 frag u_spec_scale 624 float 1 0 +U f2952361 frag u_sky_rot 632 vec2 1 0 +U f2952361 frag u_ibl_scale 640 vec3 1 0 +U f2952361 frag u_daylight 652 float 1 0 +U f2952361 frag u_fire_pos 656 vec3 1 0 +U f2952361 frag u_fire_color 672 vec3 1 0 +U f2952361 frag u_hand_pos 688 vec3 1 0 +U f2952361 frag u_hand_color 704 vec3 1 0 +U f2952361 frag u_hand_dir 720 vec3 1 0 +U f2952361 frag u_hand_cone 732 float 1 0 +U f2952361 frag u_ts_origin 736 vec2 1 0 +U f2952361 frag u_ts_half 744 float 1 0 +U f2952361 frag u_ts_on 748 float 1 0 +U f2952361 frag u_force_cascade 752 int 1 0 +U f2952361 frag u_cloud_shadow 756 float 1 0 +U f2952361 frag u_time 760 float 1 0 +U f2952361 frag u_half 764 float 1 0 +U f2952361 frag u_texel 768 float 1 0 +U f2952361 frag u_ortho_on 772 float 1 0 +U f2952361 frag u_carpet_on 776 float 1 0 +U f2952361 frag u_snow_line 780 float 1 0 +U f2952361 frag u_lake_level 784 float 1 0 +U f2952361 frag u_sea_level 788 float 1 0 +U f2952361 frag u_origin 792 vec2 1 0 +U f2952361 frag u_view 800 mat4 1 0 +U f2952361 frag u_far_split 864 float 1 0 +U f2952361 frag u_far_band 868 float 1 0 +T f2952361 u_brdf 2 +T f2952361 u_carpet 3 +T f2952361 u_grass_a 4 +T f2952361 u_grass_d 5 +T f2952361 u_grass_n 6 +T f2952361 u_height 7 +T f2952361 u_irradiance 8 +T f2952361 u_ortho 9 +T f2952361 u_prefilter 10 +T f2952361 u_rock_a 11 +T f2952361 u_rock_d 12 +T f2952361 u_rock_n 13 +T f2952361 u_shadow 14 +T f2952361 u_snow_d 15 +T f2952361 u_sunshadow 16 +T f2952361 u_tershadow 17 +T f2952361 u_ts_height 18 +P a0f2dbac terrain.vert terrain.frag #define SUN_INLINE;#define FAR_ONLY; +B a0f2dbac vert 0 204 +U a0f2dbac vert u_half 0 float 1 0 +U a0f2dbac vert u_view 16 mat4 1 0 +U a0f2dbac vert u_proj 80 mat4 1 0 +U a0f2dbac vert u_origin 144 vec2 1 0 +U a0f2dbac vert u_cam_pos 160 vec3 1 0 +U a0f2dbac vert u_node 176 vec3 1 0 +U a0f2dbac vert u_morph 192 vec2 1 0 +U a0f2dbac vert u_grid 200 float 1 0 +I a0f2dbac a_xz 0 vec2 +B a0f2dbac frag 1 872 +U a0f2dbac frag u_cascade_vp 0 mat4 5 64 +U a0f2dbac frag u_cascade_split 320 float 5 16 +U a0f2dbac frag u_cascade_range 400 float 5 16 +U a0f2dbac frag u_cascade_texel 480 float 5 16 +U a0f2dbac frag u_sun_dir 560 vec3 1 0 +U a0f2dbac frag u_sun_color 576 vec3 1 0 +U a0f2dbac frag u_cam_pos 592 vec3 1 0 +U a0f2dbac frag u_prefilter_levels 604 float 1 0 +U a0f2dbac frag u_fog_density 608 float 1 0 +U a0f2dbac frag u_fog_height_falloff 612 float 1 0 +U a0f2dbac frag u_fog_base 616 float 1 0 +U a0f2dbac frag u_clip_y 620 float 1 0 +U a0f2dbac frag u_spec_scale 624 float 1 0 +U a0f2dbac frag u_sky_rot 632 vec2 1 0 +U a0f2dbac frag u_ibl_scale 640 vec3 1 0 +U a0f2dbac frag u_daylight 652 float 1 0 +U a0f2dbac frag u_fire_pos 656 vec3 1 0 +U a0f2dbac frag u_fire_color 672 vec3 1 0 +U a0f2dbac frag u_hand_pos 688 vec3 1 0 +U a0f2dbac frag u_hand_color 704 vec3 1 0 +U a0f2dbac frag u_hand_dir 720 vec3 1 0 +U a0f2dbac frag u_hand_cone 732 float 1 0 +U a0f2dbac frag u_ts_origin 736 vec2 1 0 +U a0f2dbac frag u_ts_half 744 float 1 0 +U a0f2dbac frag u_ts_on 748 float 1 0 +U a0f2dbac frag u_force_cascade 752 int 1 0 +U a0f2dbac frag u_cloud_shadow 756 float 1 0 +U a0f2dbac frag u_time 760 float 1 0 +U a0f2dbac frag u_half 764 float 1 0 +U a0f2dbac frag u_texel 768 float 1 0 +U a0f2dbac frag u_ortho_on 772 float 1 0 +U a0f2dbac frag u_carpet_on 776 float 1 0 +U a0f2dbac frag u_snow_line 780 float 1 0 +U a0f2dbac frag u_lake_level 784 float 1 0 +U a0f2dbac frag u_sea_level 788 float 1 0 +U a0f2dbac frag u_origin 792 vec2 1 0 +U a0f2dbac frag u_view 800 mat4 1 0 +U a0f2dbac frag u_far_split 864 float 1 0 +U a0f2dbac frag u_far_band 868 float 1 0 +T a0f2dbac u_brdf 2 +T a0f2dbac u_carpet 3 +T a0f2dbac u_grass_a 4 +T a0f2dbac u_grass_d 5 +T a0f2dbac u_grass_n 6 +T a0f2dbac u_height 7 +T a0f2dbac u_irradiance 8 +T a0f2dbac u_ortho 9 +T a0f2dbac u_prefilter 10 +T a0f2dbac u_rock_a 11 +T a0f2dbac u_rock_d 12 +T a0f2dbac u_rock_n 13 +T a0f2dbac u_shadow 14 +T a0f2dbac u_snow_d 15 +T a0f2dbac u_sunshadow 16 +T a0f2dbac u_tershadow 17 +T a0f2dbac u_ts_height 18 +P 5e4589a1 terrain.vert terrain.frag #define SUN_INLINE;#define NEAR_ONLY; +B 5e4589a1 vert 0 204 +U 5e4589a1 vert u_half 0 float 1 0 +U 5e4589a1 vert u_view 16 mat4 1 0 +U 5e4589a1 vert u_proj 80 mat4 1 0 +U 5e4589a1 vert u_origin 144 vec2 1 0 +U 5e4589a1 vert u_cam_pos 160 vec3 1 0 +U 5e4589a1 vert u_node 176 vec3 1 0 +U 5e4589a1 vert u_morph 192 vec2 1 0 +U 5e4589a1 vert u_grid 200 float 1 0 +I 5e4589a1 a_xz 0 vec2 +B 5e4589a1 frag 1 872 +U 5e4589a1 frag u_cascade_vp 0 mat4 5 64 +U 5e4589a1 frag u_cascade_split 320 float 5 16 +U 5e4589a1 frag u_cascade_range 400 float 5 16 +U 5e4589a1 frag u_cascade_texel 480 float 5 16 +U 5e4589a1 frag u_sun_dir 560 vec3 1 0 +U 5e4589a1 frag u_sun_color 576 vec3 1 0 +U 5e4589a1 frag u_cam_pos 592 vec3 1 0 +U 5e4589a1 frag u_prefilter_levels 604 float 1 0 +U 5e4589a1 frag u_fog_density 608 float 1 0 +U 5e4589a1 frag u_fog_height_falloff 612 float 1 0 +U 5e4589a1 frag u_fog_base 616 float 1 0 +U 5e4589a1 frag u_clip_y 620 float 1 0 +U 5e4589a1 frag u_spec_scale 624 float 1 0 +U 5e4589a1 frag u_sky_rot 632 vec2 1 0 +U 5e4589a1 frag u_ibl_scale 640 vec3 1 0 +U 5e4589a1 frag u_daylight 652 float 1 0 +U 5e4589a1 frag u_fire_pos 656 vec3 1 0 +U 5e4589a1 frag u_fire_color 672 vec3 1 0 +U 5e4589a1 frag u_hand_pos 688 vec3 1 0 +U 5e4589a1 frag u_hand_color 704 vec3 1 0 +U 5e4589a1 frag u_hand_dir 720 vec3 1 0 +U 5e4589a1 frag u_hand_cone 732 float 1 0 +U 5e4589a1 frag u_ts_origin 736 vec2 1 0 +U 5e4589a1 frag u_ts_half 744 float 1 0 +U 5e4589a1 frag u_ts_on 748 float 1 0 +U 5e4589a1 frag u_force_cascade 752 int 1 0 +U 5e4589a1 frag u_cloud_shadow 756 float 1 0 +U 5e4589a1 frag u_time 760 float 1 0 +U 5e4589a1 frag u_half 764 float 1 0 +U 5e4589a1 frag u_texel 768 float 1 0 +U 5e4589a1 frag u_ortho_on 772 float 1 0 +U 5e4589a1 frag u_carpet_on 776 float 1 0 +U 5e4589a1 frag u_snow_line 780 float 1 0 +U 5e4589a1 frag u_lake_level 784 float 1 0 +U 5e4589a1 frag u_sea_level 788 float 1 0 +U 5e4589a1 frag u_origin 792 vec2 1 0 +U 5e4589a1 frag u_view 800 mat4 1 0 +U 5e4589a1 frag u_far_split 864 float 1 0 +U 5e4589a1 frag u_far_band 868 float 1 0 +T 5e4589a1 u_brdf 2 +T 5e4589a1 u_carpet 3 +T 5e4589a1 u_grass_a 4 +T 5e4589a1 u_grass_d 5 +T 5e4589a1 u_grass_n 6 +T 5e4589a1 u_height 7 +T 5e4589a1 u_irradiance 8 +T 5e4589a1 u_ortho 9 +T 5e4589a1 u_prefilter 10 +T 5e4589a1 u_rock_a 11 +T 5e4589a1 u_rock_d 12 +T 5e4589a1 u_rock_n 13 +T 5e4589a1 u_shadow 14 +T 5e4589a1 u_snow_d 15 +T 5e4589a1 u_sunshadow 16 +T 5e4589a1 u_tershadow 17 +T 5e4589a1 u_ts_height 18 P bf3151c8 terrain.vert tersun.frag B bf3151c8 vert 0 204 U bf3151c8 vert u_half 0 float 1 0 diff --git a/packages/ludic.render3d/shaders/terrain.frag b/packages/ludic.render3d/shaders/terrain.frag index d98afcca..f3cecb1d 100644 --- a/packages/ludic.render3d/shaders/terrain.frag +++ b/packages/ludic.render3d/shaders/terrain.frag @@ -200,6 +200,20 @@ void triC(bool cheap, sampler2D d, sampler2D nm, sampler2D am, vec3 p, vec3 dpx, if (cheap) { samplePlain(d, nm, am, p.xz * scale, dpx.xz * scale, dpy.xz * scale, alb, nrm, arm); nrm = normalize(vec3(nrm.x, 1.0, nrm.y) + vec3(0.0, 1e-3, 0.0)); } else sampleTri(d, nm, am, p, dpx, dpy, n, scale, alb, nrm, arm); } +#ifdef SUN_INLINE +// Vulkan: the cascades are read here, in the ground's own shader, and tersun.frag's pass - a second +// rasterisation of every patch - is not drawn. The cliff tersun.frag describes is OpenGL's driver, and +// OpenGL keeps that pass. The same normal, the same two tiers and the same cross-fade as tersun.frag. +uniform float u_far_split; +uniform float u_far_band; +float sunInline(vec3 p, float dist, float viewDepth) { + vec3 Ng = normalize(texture(u_height, v_huv).gba); + if (dist > u_far_split + u_far_band) return sunShadowCheap(p, Ng, viewDepth); + if (dist < u_far_split - u_far_band) return sunShadow(p, Ng, viewDepth); + return mix(sunShadow(p, Ng, viewDepth), sunShadowCheap(p, Ng, viewDepth), + smoothstep(u_far_split - u_far_band, u_far_split + u_far_band, dist)); +} +#endif vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool cheap) { // ---- material weights ---- float macro = fbmC(cheap, p.xz * 0.02, 2); @@ -411,9 +425,11 @@ vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool // ground's own relief is in the baked height-field shadow that sunShadow() applies #ifdef TFAST_1 float shadow = 1.0; +#elif defined(SUN_INLINE) + float shadow = sunInline(p, dist, viewDepth); #else // tersun.frag computed this for exactly this pixel; see the note there for why the - // cascade read cannot happen in here. + // cascade read cannot happen in here (on OpenGL). float shadow = texelFetch(u_sunshadow, ivec2(gl_FragCoord.xy), 0).r; #endif vec3 col = shade(p, n, alb, rough, metal, ao, shadow, viewDepth); @@ -421,8 +437,10 @@ vec3 groundShade(vec3 p, vec3 N, float slope, float dist, float viewDepth, bool return col; } +#ifndef SUN_INLINE uniform float u_far_split; uniform float u_far_band; +#endif void main() { vec3 p = v_wpos; if (p.y < u_clip_y) discard; diff --git a/packages/ludic.render3d/shaders/variants.list b/packages/ludic.render3d/shaders/variants.list index 64674722..5ac3cca9 100644 --- a/packages/ludic.render3d/shaders/variants.list +++ b/packages/ludic.render3d/shaders/variants.list @@ -46,5 +46,8 @@ skin.vert|shadow.frag|#define SHADOW_PASS;#define ALPHA_TEST; terrain.vert|terrain.frag| terrain.vert|terrain.frag|#define FAR_ONLY; terrain.vert|terrain.frag|#define NEAR_ONLY; +terrain.vert|terrain.frag|#define SUN_INLINE; +terrain.vert|terrain.frag|#define SUN_INLINE;#define FAR_ONLY; +terrain.vert|terrain.frag|#define SUN_INLINE;#define NEAR_ONLY; terrain.vert|tersun.frag| water.vert|water.frag| diff --git a/packages/ludic.render3d/terrain.ludic b/packages/ludic.render3d/terrain.ludic index f5efdd15..9d7da8c7 100644 --- a/packages/ludic.render3d/terrain.ludic +++ b/packages/ludic.render3d/terrain.ludic @@ -32,6 +32,7 @@ var ter_prog: int = 0 var ter_prog_far: int = 0 var ter_prog_near: int = 0 # the detailed tier alone (NEAR_ONLY) var ter_sun_prog: int = 0 # tersun.frag: sun visibility into a screen buffer +var ter_sun_inline: bool = false # the ground's shader reads the cascades itself (Vulkan); no sun pass var ter_sun_tgt: Target = null # that buffer, at the frame's size var ter_sun_refl: Target = null # and at the reflection's, which is smaller var ter_sun_dumped: bool = false @@ -423,6 +424,11 @@ function terrain_init_finish() -> void { # draw every patch with one tier's program (what each tier costs over a whole frame); # R3D_NOSPLIT goes back to the single program that holds both tiers. if Os.has_env("R3D_TFAST") { defs = defs + "#define TFAST_" + Os.env("R3D_TFAST") + "\n" } + # Vulkan reads the cascades inside the ground's own shader and draws no separate sun pass + # (terrain.frag, SUN_INLINE): one rasterisation of the patches instead of two, in the frame and in + # the reflection. R3D_SUN_PASS=1 keeps the pass there too, for comparing. + ter_sun_inline = gpu_kind == GPU_VK and not Os.has_env("R3D_SUN_PASS") + if ter_sun_inline { defs = defs + "#define SUN_INLINE\n" } ter_prog = r3d_program("terrain.vert", "terrain.frag", defs) ter_prog_far = r3d_program("terrain.vert", "terrain.frag", defs + "#define FAR_ONLY\n") ter_prog_near = r3d_program("terrain.vert", "terrain.frag", defs + "#define NEAR_ONLY\n") @@ -487,9 +493,12 @@ function terrain_bind_prog(p: int) -> void { # The ground reads its sun visibility out of the buffer tersun.frag filled, and has no # use for the cascade array shadow_bind just put on this unit; leaving both bound under # one unit is undefined ground, so the array comes off first. - gpu_tex_unit(15) - gpu_tex_bind(GPU_TEX2D_ARRAY, 0) - r3d_bind_2d(p, "u_sunshadow", 15, ter_sun_tex) + # (With the read inline, the array shadow_bind put there is exactly what the ground wants.) + if not ter_sun_inline { + gpu_tex_unit(15) + gpu_tex_bind(GPU_TEX2D_ARRAY, 0) + r3d_bind_2d(p, "u_sunshadow", 15, ter_sun_tex) + } } # The visibility buffer for the size being drawn into. The reflection is rendered at its @@ -559,6 +568,7 @@ function terrain_sun_pass(w: int, h: int, depth: int) -> Target { } function terrain_sun_prepare() -> void { + if ter_sun_inline { return } ter_sun_tex = terrain_sun_pass(post_w, post_h, post_hdr.depth).color ter_sun_done = true } @@ -571,7 +581,7 @@ function terrain_draw() -> void { var vw = post_w var vh = post_h if ter_reflect { vw = water_refl.w; vh = water_refl.h } - if not ter_sun_done { + if not ter_sun_done and not ter_sun_inline { var dep = post_hdr.depth if ter_reflect { dep = water_refl.depth } ter_sun_tex = terrain_sun_pass(vw, vh, dep).color