So this took a lot of effort, and even more to make it reasonably usable. The current API looks like this:
let vertex_buffer = chai::graphics::VertexBuffer::new(&mut VERTICES, &mut renderer.gfx); let shader = chai::graphics::ShaderBuilder::new("main") .with( "basic.vert", chai::graphics::ShaderType::Vertex, &mut renderer.gfx, ) .with( "basic.frag", chai::graphics::ShaderType::Fragment, &mut renderer.gfx, ) .build::<Vertex>(&mut renderer.gfx);
There are a few things that are not great about this. Firstly I don't like that you have to pass around the graphics state (
renderer.gfx) to everything. That said it is much better than dealing with a singleton which in rust is a real pain. In the future I will probably put a wrapper around the renderer that automatically passes the state to the relevant bits. Other than this I am very happy with how this turned out, there are still a few places in the api that need to be fixed. For example
Shaders can't have any entries other than vertex and fragment at this point. This isn't that bad right now, but in the future it will be less than ideal, also right now shaders are read in from files at runtime, which isn't bad for debug (in fact it is a good thing) but for release they should be read and compiled at compile time.
Some of the next steps will most likely be to get index buffers working, followed by some basic primitives. Also documentation is lacking right now. After that hopefully images. Looking forward this is the kind of api I want for the primatives:
let rect = graphics::Rect::new(0, 0, 100, 100); rect .with_color(chai::Color::new_from_rgb(0, 0, 255)) .with_rotation(30); // rotate 30deg, I haven't decided if it should be rad or deg yet, similar functions for translation, skew, etc. // ... renderer.draw(rect);
There are a few issues with this kind of api however it isn't anything too bad, and it is a good start. So what do I need to have this work
- index buffers
- transform maths
- a more robust renderer
- a better way to handle shaders
- standardized vertex layouts
- custom vertex layouts
- at least 50 other things that I don't even know about yet
Fortunately I believe that the worst is behind me now for the foreseeable future. I understand the basics of graphics programming at this level, at least enough to know what to do. When 3D stuff eventually happens this mess will start again but that isn't for a while yet.
I did some hard thinking and realized that the current way I was handling deciding what graphics backend to use was flawed. Firstly while it did "work" it didn't actually work, this could have been fixed relatively easily but it got me thinking about how the backend will never change during runtime, so why not change it to be many different executables and have them be chosen from in a launcher. This still sucks, I don't like launchers on principle, they always feel very bloated and kinda useless to me. Furthermore it would cause the client to have to deal with a whole other thing to make instead of just working on their application. So the compromise I have come to is what I call "invisible launchers." While I am sure these have been thought of and used before I have never seen them in practice and they are new to me. Though I also don't play a lot of games. The entire code for an invisible launcher can be summed up as: reading a file, and launching the appropriate exe. So they don't need a gui, they don't even need a window. So this to me solves almost every problem, the only remaining one is that the download size for the final installer will be larger, that said I don't think that is too big of a price to pay.