render3d(vulkan): the ground reads the sun cascades itself - no separate terrain sun pass
tersun.frag rasterised every terrain patch a second time into a screen buffer, because on OpenGL the cascade read inside terrain.frag fell off a driver cliff (about 6 ms a frame). Vulkan has no such cliff: its terrain programs are the SUN_INLINE variant, which evaluates the same two tiers with the same normal and cross-fade in the ground's own shader, and terrain_draw skips the pass - in the frame and in the water reflection. OpenGL keeps the pass. R3D_SUN_PASS=1 keeps it on Vulkan, for comparing. Mac Vulkan town 1759 -> 1692 draws; frames within 2/255 of the pass (15331 px, float rounding). PC camp 1984 -> 1882 draws, 3.9 s for 400 frames either way, self-tests 59/59, validation 0. OpenGL frames byte-identical. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
eb1cd3e01a
commit
44ecd55a86
10 changed files with 240 additions and 5 deletions
BIN
packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv
Normal file
BIN
packages/ludic.render3d/shaders/spv/5e4589a1.frag.spv
Normal file
Binary file not shown.
BIN
packages/ludic.render3d/shaders/spv/5e4589a1.vert.spv
Normal file
BIN
packages/ludic.render3d/shaders/spv/5e4589a1.vert.spv
Normal file
Binary file not shown.
BIN
packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv
Normal file
BIN
packages/ludic.render3d/shaders/spv/a0f2dbac.frag.spv
Normal file
Binary file not shown.
BIN
packages/ludic.render3d/shaders/spv/a0f2dbac.vert.spv
Normal file
BIN
packages/ludic.render3d/shaders/spv/a0f2dbac.vert.spv
Normal file
Binary file not shown.
BIN
packages/ludic.render3d/shaders/spv/f2952361.frag.spv
Normal file
BIN
packages/ludic.render3d/shaders/spv/f2952361.frag.spv
Normal file
Binary file not shown.
BIN
packages/ludic.render3d/shaders/spv/f2952361.vert.spv
Normal file
BIN
packages/ludic.render3d/shaders/spv/f2952361.vert.spv
Normal file
Binary file not shown.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue