Quick answer: GameMaker shader_get_uniform returning -1 even though the uniform exists in the shader? The uniform was optimized out because nothing uses it — reference it in the shader code path or it’s stripped.

A water shader takes u_amplitude but shader_get_uniform returns -1. The variable is declared but never read in the fragment, so the compiler dropped it.

Optimizer Drops Unused

GLSL/HLSL compilers strip unused uniforms. If u_amplitude isn’t referenced in any code path, the linker sees no use and removes it. shader_get_uniform can’t find what isn’t there.

Reference It

Make sure the uniform is actually read — even gl_FragColor.r += u_amplitude * 0.0001; keeps it alive for testing. Once you wire it for real, it stays.

Cache Locations

// in Create
u_amp_loc = shader_get_uniform(shd_water, "u_amplitude");
// in Draw
shader_set_uniform_f(u_amp_loc, amp);

Looking up per-frame is wasted work — cache once.

Verifying

The uniform location is ≥ 0, shader_set_uniform_f takes effect, and the shader visibly responds.

“Unused uniforms get optimized out. Reference them in a real code path.”

Don’t guess — log uniform locations at startup. If one is −1 you know immediately, not after the artist reports a broken effect.