render3d: grass in chunks of 256 tiles a draw, flower casters only into the cascades they reach
Grass (Vulkan with multi-draw indirect): every visible tile is a record in one buffer, uploaded once a frame, and each band draws its records 256 at a time. A record's firstInstance is its place in the chunk times 65536; grass.vert's TILES variant reads that place's corner and indices per cell from u_tiles. R3D_GRASS_TILES=1 keeps a draw per tile. OpenGL is unchanged. Casters: a LOD level with no impostor is drawn into a shadow cascade only when its distance band, widened by six times its height, the camera's height over the ground and the frustum's corner reach, can touch that cascade's receivers. The flowers' mesh levels (6 - 30 m) leave the three outer cascades. R3D_CAST_ALL=1 draws every level everywhere. OpenGL frames byte-identical at all five viewpoints; alpha-tested shadow draws at a 460 -> 244. gpu_has_mdi() guards both this and the GPU-culled trees' multi-record draws. Camp: Mac Vulkan 2645 -> 2191 (grass) -> 2034 draws; PC 2657 -> 2046, self-tests 59/59, validation 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d8300a7bf9
commit
cdfffa62bb
9 changed files with 202 additions and 9 deletions
|
|
@ -27,6 +27,9 @@ uniform float u_wind;
|
|||
uniform vec2 u_tile; // world xz of this tile's corner
|
||||
uniform int u_tile_cells; // 16 m cells per tile side
|
||||
uniform int u_per_cell; // indices drawn per cell in this tile
|
||||
#ifdef TILES
|
||||
uniform vec4 u_tiles[256]; // per tile of the draw: corner x, corner z, indices per cell
|
||||
#endif
|
||||
uniform float u_s0; // blade spacing at the camera (m)
|
||||
uniform float u_d0; // distance at which the spacing has doubled (m)
|
||||
uniform float u_radius; // no blades past this
|
||||
|
|
@ -66,10 +69,21 @@ float heightSmooth(sampler2D tex, vec2 uv) {
|
|||
void cull() { gl_Position = vec4(0.0, 0.0, 2.0, 1.0); v_wpos = vec3(0.0); v_nrm = vec3(0.0, 1.0, 0.0); v_uv = vec2(0.0); v_seed = 0.0; v_rot = vec2(0.0, 1.0); v_hull = 1.0; }
|
||||
|
||||
void main() {
|
||||
#ifdef TILES
|
||||
// Vulkan: one draw covers a chunk of tiles. Each record's firstInstance is its place in the chunk
|
||||
// times 65536 (grass.ludic), and u_tiles holds that place's corner and indices per cell.
|
||||
int ti = gl_InstanceIndex / 65536;
|
||||
int i = gl_InstanceIndex - ti * 65536;
|
||||
vec2 tile = u_tiles[ti].xy;
|
||||
int per_cell = int(u_tiles[ti].z + 0.5);
|
||||
#else
|
||||
int i = gl_InstanceID;
|
||||
int c = i / u_per_cell;
|
||||
int j = i - c * u_per_cell;
|
||||
vec2 cell = u_tile + vec2(float(c % u_tile_cells), float(c / u_tile_cells)) * CELL;
|
||||
vec2 tile = u_tile;
|
||||
int per_cell = u_per_cell;
|
||||
#endif
|
||||
int c = i / per_cell;
|
||||
int j = i - c * per_cell;
|
||||
vec2 cell = tile + vec2(float(c % u_tile_cells), float(c / u_tile_cells)) * CELL;
|
||||
vec2 cid = floor(cell / CELL + 0.5);
|
||||
ivec2 ci = ivec2(cid);
|
||||
float fj = float(j);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue