raduprv / Eternal-Lands

http://www.eternal-lands.com
Other
154 stars 56 forks source link

GLES 3 branch #172

Open raduprv opened 2 years ago

raduprv commented 2 years ago

Anyone interested in starting a GLES3 branch? Nothing fancy, just port the client to GLES3. That way, we can later add fancier stuff, such as custom shaders, etc. I think only Grum has some shader experience, but I was thinking to start learning a bit of GLES3 myself.

gvissers commented 2 years ago

just port the client to GLES3

"just"? I think it would be a rather large rewrite, as all the rendering code (excepting the code paths for the 3D objects already using VBOs) would need to be rewritten. It might be worthwhile, though, and would rid us of gl4es on Android. Have you looked at alternatives, Vulkan for instance?

I think only Grum has some shader experience

And precious little at that. Then again, setting up a basic shader pipeline to render the world is not that difficult; if you disregard lighting and shadows it's even trivial. So I certainly think it's doable, just a lot of work. Might be a good idea to do it piecemeal, e.g. use OpenGL2 compatibility profile at first (maybe we're already using that?) and get rid of the immediate mode GL bit by bit, then switch to GLES3 profile and see what breaks :laughing: After that we could add fancier stuff if any good ideas come up.

raduprv commented 2 years ago

By "just" I meant just the basic shader pipeline. I know there is a lot of code, mainly in the GUI that needs to be ported. Getting rid of gl4es is just one nice thing, the other will be that we can 'borrow' shaders and have a more optimal client so we can increase the number of triangles and such.

As for Vulkan, I think that's too new and we'd lose compatibility with some older devices. It might work only if we have two rendering paths, the current one and Vulkan. Besides, GLES works on the web, Vulkan doesn't. I remember that a long time ago you started a webgl 'port'. If we port the entire client to GLES it would be much easier to do a webgl port.

pjbroad commented 2 years ago

I'd be interested in this too though I'd have to learn a lot. The gl4es library is amazingly good but we're stuck on an old version and the thought of wrangling the client to the latest version is more daunting to me than learning a new library.

raduprv commented 2 years ago

Ok, great :) Now there is one question remaining. It would be a good idea to keep the Opengl 1.2 rendering path, at least for a while, to maintain compatibility with really old desktop systems. We can do this by either having #ifdefs all over the code, and compiling two versions, or we can have both rendering paths in the client and select which one we want at runtime.

Here is a tutorial that covers most, if not all our needs (possibly with the exception of the shadows and reflections): https://keasigmadelta.com/store/wp-content/uploads/2017/03/GLES3-and-SDL2-Tutorials.pdf

What we have to do, after we set up the vertex and fragment shaders for 3d objects is to have a 2d vertex and fragment shader and replace all the GLbegin/end code with the shaders. It's probably a lot of repetitive, boring work. I can assist in that too if needed.

gvissers commented 2 years ago

we can have both rendering paths in the client and select which one we want at runtime.

This, please, if we can manage it. It would be very nice if we could separate the rendering from the data and other functionality. If only so that it would be easier to add other backends in the future (like libcaca :wink: ).

raduprv commented 2 years ago

Yes, I agree, the second path would be nicer. Not sure if we can separate the data from the rendering code (without a total rewrite) but I guess we can use ifs() in every function to select multiple rendering paths.

gvissers commented 2 years ago

Well, it's certainly possible to use GL ES. With some tweaking I managed to convince merel (my hobby program in Rust that some day in the very far future is supposed to become a better map editor for EL) to render using GLES 3.0: IP_gles3 So there's no lighting, reflections, actors, or anything else that makes this a game, but the basics work. I tried GLES 2.0 at first, but there's just too much stuff not included (VAO's, glDrawRangeElements, half floats to name a few) that I decided it wasn't worth the trouble. GLES3 seems nice enough though (but it seems to lack geometry shaders, not too much of an issue).

raduprv commented 2 years ago

So the very first thing we should do is probably make some basic abstraction layer for the UI. I think there are two possible paths for this.

  1. Abstract the basic UI elements (such as draw_line() and draw_2d_sprite()) and use what we have.
  2. Draw the GUI itself (each window) in a texture instead (on the CPU) and send it to the GPU, then update the texture if anything changes. This might be faster, since it does fewer GL calls. Our interface doesn't change that often, so...
xaphier commented 2 years ago

Hi all,

I am back after being very busy with family stuff for the last years. Too much family members died of cancer. I can chip in my graphic programming expertise. If I recall correctly, the ui rendering is probably the biggest task. Especially the line drawing stuff is painful to "emulate"/map to modern graphic api's.

raduprv commented 2 years ago

Sorry again for your family losses. We are glad that you are back! So what do you think we should do about the UI? Should we build it on the CPU side, in a texture?

xaphier commented 2 years ago

I am not sure writing a pure CPU based renderer is going to work. If I remember, we also have textures/icons/images in the ui that are scaled. I would suggest to take a look at imgui. Maybe we can copy some of the ideas there.

raduprv commented 2 years ago

I remembered that we also draw lines in other places, such as the arrows. Is it too hard, or too expensive or why can't we emulate drawing lines in GLES 3?

gvissers commented 2 years ago

Hey Xaphier, good to see you back. I am very sorry to hear about your loss, my condolences.

As for lines, what's the problem? Doesn't GLES 3 support lines? Well, worst case, we can draw quads, but I don't think its insurmountable.

xaphier commented 2 years ago

Of course it's not impossible. The only geometry left in modern graphic api's are triangles. triangles and triangle strips. So of course it's possible to emulate line drawing by using triangles to make small screen aligned rectangles (four vertexes and two triangles per line segment).

raduprv commented 2 years ago

I think it would be best to just have to primitives, line and box, and have wrappers for them for OpenGL 1.2 and GLES 3. That should solve most of the GUI issues, no?

pjbroad commented 2 years ago

Hey @xaphier nice to see you. Sorry to hear you've had a tough time.

gvissers commented 2 years ago

BTW, if we do this, can we please start using GLEW and drop load_gl_extension.[ch]? I really don't look forward to adding 15 years of OpenGL extensions, and I've always found the El prefix on the OpenGL functions distracting.

raduprv commented 2 years ago

How exactly would it help to add yet another dependency? Do we need all the 15 years worth of extensions? Don't we only use a few?

gvissers commented 2 years ago

It's not a huge dependency, and GLEW is a well known and well maintained library. It can easily be statically linked, so we would not have to ship the library itself either. Using it would rid us of of (most of) both glext.h and load_gl_extensions.[ch], which contain literally thousands of lines of declarations and defines. And it's not only 15 years of extensions we'd have to add, but also OpenGL functionality itself.

On the other hand, it would mean a lot of code churn, as we'd probably have to rename all the ELgl*() calls. So I can see the case for limping along and only declaring what we use. But IMHO the GLES3 branch would be a good opportunity to clean this up and shove maintenance of this part off to someone else :laughing:

xaphier commented 2 years ago

I looked at bit more what we would need to get the ui converted. Since all the matrix transformation functions are not part of modern graphic api's (glTranslate, glRotate, glScale* etc) and we use them currently, a replacement for them is needed. We need 2D, 3D & 4D (for perspective stuff) matrices and vectors. I personally have ever only used glm. What are your comments/suggestions?

gvissers commented 2 years ago

I have no other suggestions, I have only used the cgmath crate with rust, and eigen in c++ , but that seems a bit overkill for this. Glm looks fine to me, and I have seen it used in a lot of other projects. The disadvantage I can see is that it's c++ only, and we still have a bunch of C code. We 'd have to write wrappers, or do all rendering in C++.

raduprv commented 2 years ago

How about https://github.com/datenwolf/linmath.h ? It's C and it's supposed to be for glsl.

xaphier commented 2 years ago

Looks fine for me. That would also make the first work step clear. Replacing all the glTransform, glScale, glRotate etc. with explicit computations and only loading the final matrices with glLoadMatrix. This can be done step by step and doesn't affect the required minimal OpenGL version.

gvissers commented 2 years ago

That would also make the first work step clear. Replacing all the glTransform, glScale, glRotate etc. with explicit computations and only loading the final matrices with glLoadMatrix.

Yes, please. The sooner we get rid of as much implicit state, the better.

xaphier commented 2 years ago

How do we want to consume the linmath.h ? Direct include? Git submodule? User supplied + CMake based search?

raduprv commented 2 years ago

I think direct include would be best, no?

gvissers commented 2 years ago

For the JSON dependency, the headers are included in the client source tree, but one needs to enable a build flag to use those. By default the user system includes are used. Perhaps we can do something similar for linmath.

raduprv commented 2 years ago

I don't think we can/should use a build flag for linmath if we do what xaphier suggested. They will be necessary for all the matrix math, both for the OpenGL 1.x branch and for GLES 3.1 branch.

gvissers commented 2 years ago

No, the build flag determines whether the system library is used or the one in the client source, not whether it's used at all. Obviously we will need the functionality. We can of course quibble about which choice should be default. Personally I like my bike sheds forest green.

raduprv commented 2 years ago

It's just a header, no? What's the sense in having it as a system library? I think it only makes sense to use the header we provide, because this is what we build and test the game with.

raduprv commented 2 years ago

Any thoughts about using the BGFX library for this?

xaphier commented 2 years ago

BGFX looks like it has it's own rendering abstraction, so it is higher level than opengl/vulkan/etc. That means all opengl code would need to be replaced, not just the matrix transformations. I would suggest we first do the matrix stuff. As a general update, I think I have a better overview and can start pushing the first changes replacing all the matrix stuff soon.