garrysmod-requests icon indicating copy to clipboard operation
garrysmod-requests copied to clipboard

Add IMaterial:SetFloat4( x, y, z, w )

Open Srlion opened this issue 10 months ago • 15 comments

Details

Having this function can save performance on really simple shaders by avoiding the round trips between Lua and C++, as it will only be two trip from 8 trips.

mat:SetFloat4("$c0", 1, 1, 1, 1) -- two C calls as mat.__index is a C one

vs

-- 8 C Calls
mat:SetFloat("$c0_x", 1)
mat:SetFloat("$c0_y", 1)
mat:SetFloat("$c0_z", 1)
mat:SetFloat("$c0_w", 1)

Srlion avatar Jan 29 '25 21:01 Srlion

Does this not fulfill that purpose? https://wiki.facepunch.com/gmod/IMaterial:SetVector4D

Edit: Oh nevermind you want it to magically fill out different parameters

robotboy655 avatar Jan 29 '25 21:01 robotboy655

Edit: Oh nevermind you want it to magically fill out different parameters

Wouldn't it just work like SetVector4D?

Srlion avatar Jan 29 '25 22:01 Srlion

Material parameters each have a type. Each function sets only 1 material parameter. You want a function that sets 4 individual material parameters, while assuming their names.

robotboy655 avatar Jan 29 '25 22:01 robotboy655

Could probably change the shader/material parameter to just be a vector4 instead of 4 separate ones, but idk.

robotboy655 avatar Jan 29 '25 22:01 robotboy655

Material parameters each have a type. Each function sets only 1 material parameter. You want a function that sets 4 individual material parameters, while assuming their names.

I'm not following, isn't float4 in shaders always x y z w? How would it need to assume their names?

Srlion avatar Jan 29 '25 22:01 Srlion

I will try to change it to vector4 as they probably have same memory layout so maybe it could work? lol

Srlion avatar Jan 29 '25 22:01 Srlion

I'm not following, isn't float4 in shaders always x y z w? How would it need to assume their names?

Imo, it's not a good practice to have functions assume the x,y,z,w suffix when setting parameters. Maybe an optional parameter for SetVector4D, but I am not really sure what's the best option to tackle this request is.

I will try to change it to vector4 as they probably have same memory layout so maybe it could work? lol

That is very unlikely to work, I meant changing the parameters from my end to just be a vector4.

robotboy655 avatar Jan 29 '25 22:01 robotboy655

You are basically asking for a function that is only useful for 1 shader.

robotboy655 avatar Jan 29 '25 22:01 robotboy655

I'm not sure if there is any other way to pass parameters to shaders without using float4, maybe currently it will only be useful for this use-case but more people will start using it once you release thirdparty shaders and it would be better practice for them to use it. if someone is using all constants, the amount of C calls's cost will probably outweigh the cost of drawing the shader itself.

Your idea of adding optional parameter for SetVector4D is probably the best call.

Srlion avatar Jan 29 '25 22:01 Srlion

It is indeed a stinky solution. What could be a better one is batched var changes, ala:

mat:SetFloats {
  ["$c0_x"] = 1,
  ["$c0_y"] = 1,
  ["$c0_z"] = 1,
  ["$c0_w"] = 1
}

This, however, is an allocation. Another way, that only uses stack, is this:

mat:SetFloats("$c0_x", 1, "$c0_y", 1, "$c0_z", 1, "$c0_w", 1)

This is, possibly, not exactly optimal if we consider developer experience and type declaration stuff, but its pretty efficient as it only works with the stack.

artemking4 avatar Jan 29 '25 22:01 artemking4

It is indeed a stinky solution. What could be a better one is batched var changes, ala:

mat:SetFloats { ["$c0_x"] = 1, ["$c0_y"] = 1, ["$c0_z"] = 1, ["$c0_w"] = 1 }

This, however, is an allocation. Another way, that only uses stack, is this:

mat:SetFloats("$c0_x", 1, "$c0_y", 1, "$c0_z", 1, "$c0_w", 1)

This is, possibly, not exactly optimal if we consider developer experience and type declaration stuff, but its pretty efficient as it only works with the stack.

For former one I can just use a local table and change values inside it, but it won't be viable for people to use it if they are calling lots of them. The latter could work too but I prefer having an optional parameter to SetVector4D as it's simple with less work to do for us/him lol

Srlion avatar Jan 29 '25 22:01 Srlion

The second solution is rather simple from the C side, so its not that much work imo.

artemking4 avatar Jan 29 '25 22:01 artemking4

Both would be very fast indeed, any of them would be better than 8 trips.

Srlion avatar Jan 29 '25 22:01 Srlion

After thinking about it, artemking4's latter solution seems the best. It can allow any number of floats to set and also having the power of setting it for any key, also it's not hard to read/write:

mat:SetFloats(
    "$c0_x", 1,
    "$c0_y", 1,
    "$c0_z", 1,
    "$c0_w", 1,
    ...rest
)

Srlion avatar Feb 05 '25 19:02 Srlion

After thinking about it, artemking4's latter solution seems the best. It can allow any number of floats to set and also having the power of setting it for any key, also it's not hard to read/write:

mat:SetFloats( "$c0_x", 1, "$c0_y", 1, "$c0_z", 1, "$c0_w", 1, ...rest )

We can develop this even further and come up with something like this:

-- Through stack
material:SetParameters(

	'$<parameter1>', <any>,
	'$<parameter2>', <any>,
	'$<parameter3>', <any>,
	...

)

-- Through table
material:SetKeyValues( {
	
	['$<parameter1>'] = <any>,
	['$<parameter2>'] = <any>,
	['$<parameter3>'] = <any>,
	...

} )

noaccessl avatar Mar 26 '25 08:03 noaccessl