ludic/packages/ludic.render3d/grass_bind.ludic
Orkuncakilkaya e908672034 render3d: a grass kind - the GPU blades' per-kind numbers are a GrassKind record the game hands over (grass_kind_set), not constants
GrassKind (grass_kind.ludic) carries what grass.ludic, grass_gpu.ludic, grass.vert, grass_cull.comp and
model.frag's BLADE path held as constants: the cell, s0 / d0 / radius, the row bands and rows, the blade
profile (neck, root, swell, tip, bend), the heights, clumps, widths and arch, where it grows (slope, snow,
the photograph's test), the root / tip / gone-to-seed colours, the far tufts, the root occlusion, the
roughness, the sheen and the wind. Its defaults are those constants exactly, so a game that sets nothing
draws as before. The shaders read them as u_gk_* (the cull as five more Params vec4s, 288 bytes);
grass_reset.comp writes each band's index count so a kind of other rows reaches the draw in order.
grass_quality holds the kind to a settings tier (never denser, never farther); R3D_GRASS_* still win.
grass_profile_w / _bend are the one profile, for the meshes and a game's preview. grass.mesh takes only
the cell: the rest of it is an older copy that already differs from grass.vert, left as it draws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:15:39 +03:00

36 lines
2.7 KiB
Text

# ============================================================================
# grass_bind.ludic — the kind's numbers into the blade programs: the per-vertex path (grass.vert),
# the cull's Params (grass_cull.comp, gg_params) and model.frag's BLADE colouring, which the
# scatter's blade layers share. Four floats a uniform, named u_gk_*.
# ============================================================================
# the vertex stage's (grass.vert; grass.mesh reads only the cell) and the fragment stage's
function grass_bind_kind(render3d_st: mut Render3dState, p: int) -> void {
let k = grass_kind(render3d_st)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_tall"), k.tall_min, k.tall_max, k.cell_lo, k.cell_hi)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_grow"), k.tall_far, k.width, k.width_far, k.clump_freq)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_clump"), k.clump_lo, k.clump_hi, k.arch, k.arch_var)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_ground"), k.slope_lo, k.slope_hi, k.snow_in, k.snow_out)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_ortho"), k.ortho_floor, k.ortho_gain, k.ortho_green, float(render3d_st.grass_cell))
grass_bind_look(render3d_st, p)
}
# model.frag's BLADE path: the blades gone to seed, the far tufts, the root's occlusion, the roughness
function grass_bind_look(render3d_st: mut Render3dState, p: int) -> void {
let k = grass_kind(render3d_st)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_seed"), k.seed_r, k.seed_g, k.seed_b, k.seed_mix)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_look"), k.seed_lo, k.seed_hi, k.tuft_mix, k.tuft_shade)
u_f4(render3d_st, gpu_uniform(render3d_st, p, "u_gk_mat"), k.ao_root, k.rough, 0.0, 0.0)
}
# grass_cull.comp's Params from word 52: the same four vec4s as u_gk_tall .. u_gk_ortho, then the
# bands' outer distances into word 36 (they were GG_NEAR and GG_MID)
function grass_params_kind(render3d_st: mut Render3dState, pr: words) -> void {
let k = grass_kind(render3d_st)
pr[36] = float_bits(k.band_near); pr[37] = float_bits(k.band_mid)
pr[52] = float_bits(k.tall_min); pr[53] = float_bits(k.tall_max); pr[54] = float_bits(k.cell_lo); pr[55] = float_bits(k.cell_hi)
pr[56] = float_bits(k.tall_far); pr[57] = float_bits(k.width); pr[58] = float_bits(k.width_far); pr[59] = float_bits(k.clump_freq)
pr[60] = float_bits(k.clump_lo); pr[61] = float_bits(k.clump_hi); pr[62] = float_bits(k.arch); pr[63] = float_bits(k.arch_var)
pr[64] = float_bits(k.slope_lo); pr[65] = float_bits(k.slope_hi); pr[66] = float_bits(k.snow_in); pr[67] = float_bits(k.snow_out)
pr[68] = float_bits(k.ortho_floor); pr[69] = float_bits(k.ortho_gain); pr[70] = float_bits(k.ortho_green); pr[71] = float_bits(float(render3d_st.grass_cell))
}