tjammer / raylib-ocaml

OCaml bindings for raylib and raygui
https://tjammer.github.io/raylib-ocaml/
MIT License
168 stars 13 forks source link

No float uniforms? #44

Closed FayCarsons closed 1 week ago

FayCarsons commented 3 weeks ago

I noticed this section of the raymarching example:

let runtime_v = Vector2.create state.time 0. in
set_shader_value
    shader
    locations.time
    (to_voidp (addr runtime_v))
    ShaderUniformDataType.Float;

Is it not possible to set a float uniform with a float scalar? Is this just a consequence of using a bindgen or is there a reason it's this way? It seems cumbersome and potentially inefficient.

Is this something that can be solved with a PR? This library has the potential to be my primary graphics tool, I'd be happy to fix this and anything else that needs work.

tjammer commented 3 weeks ago

There are two reasons for it.

The first is that the raylib shader API is closely modelled after openGL, because that's what it uses under the hood. In openGL, the way shaders are set is by passing a void ptr and a type enum, since it's a C API. Raylib inherits this. Because we need a pointer, we need to allocate it somewhere, and that's what we're doing with Vector2.create.

The second reason is that OCaml's float has a different memory representation than C floats. In OCaml, floats are 63 bit values, in C they are 32 bit. Thus, some conversion has to be done between the two.

That said, there's no reason to allocate two floats (by using Vector2.create) instead of one. The bindings are based on ocaml-cytpes and we can use it directly to create values. We could have used Ctypes.allocate to allocate only one float.

And, we could wrap this into a function such that it accepts OCaml float literals:

let set_shader_value_float shader location value =
  let runtime_v = Ctypes.(allocate float value) in
  set_shader_value shader location (to_voidp runtime_v)
    ShaderUniformDataType.Float
tjammer commented 3 weeks ago

As for your question: I don't think we need an extra function for this in the bindings. If the use case comes up often enough, the user can still define it themselves. I changed the raymarching example though to only allocate one float (https://github.com/tjammer/raylib-ocaml/commit/577899c0925f8cbd66bb8351f1d44b78490f4785). This demonstrates how to use Ctypes directly.