MarkelZ / pygame-light2d

Fast 2D dynamic lighting engine for Pygame.
MIT License
16 stars 0 forks source link

Suggestion: upgrading it to a shader engine #4

Open OlaKenji opened 10 months ago

OlaKenji commented 10 months ago

Hi again, as I wrote in the other post, something to consider for this is if it is possible to upgrade it to a general "shader engine". For example, if the user would like to add a costume shader, the user have to go into the source and modify it so that it reads in the costume shader files and add some lines for the rendering.

If on the other hand one could split your light_engine into 1) light shader part and 2) a general shader engine, the shader engine could handle the light shader stuff and also any other user input costume shaders.

I am not sure how easy or difficult it will be to implement something like this but perhaps something to have in mind. :)

MarkelZ commented 10 months ago

@OlaKenji Hi!! Thanks for the suggestion, it's a very good idea :)

Since this lighting engine is already implemented, I think it would be better to create a new project for custom shaders in pygame.

I found two python packages that do something similar: https://pypi.org/project/PygameShader/ https://pypi.org/project/pygame-shaders/

However, these two packages are very limited. From what I've seen, they allow just one shader per draw call, which is applied to the whole screen. They also don't really provide access to a lot of useful OpenGL functionality.

In contrast, if my general shader engine were to allow as much OpenGL functionality as possible, I would end up creating moderngl all the way from scratch, and using the package would be the same as doing OpenGL with some extra abstractions.

So, I think the shader engine should sit somewhere in the middle, where it's not as limited as the other pygame shader packages, but it's not like writing straight up OpenGL either.

Do you think this would be a good idea? Also, do you have suggestions for what kind of functionality it should offer?

OlaKenji commented 10 months ago

I think what you are suggesting is very resonable! :D

As for functionalities, I think the ability to choose a specific shader (and maybe even select specific area that it should affect?) could be useful? Like, to read in your own written shader and/or select already pre-programmed shaders: for example your light shader, some water shader, "wind shader" for trees, or some "area blurring" (like in LInk's awakening switch) etc.

What do you think? Do you think this kind of engine is doable?

MarkelZ commented 10 months ago

@OlaKenji Yes it is very doable and shouldn't be too difficult to implement.

Your suggestion of applying a shader to a specific area of the screen is a bit unconventional. I would propose this instead:

This functionality should let you implement all the effects you describe. For example for the water effect, render a water texture with some distortion to make it look wavy. Also, you could apply a shader to a specific area of the screen no problem, because you can take the texture of the screen (since it's a layer) and apply a shader to a cropped subsection.

Unfortunately I am very short on time currently because of work :/

I really like your shader engine idea though and I think I'll be able to work on it at the end of October, I'll keep you posted!

MarkelZ commented 7 months ago

@OlaKenji Hello! It took a while but I did it! Here's the repo: https://github.com/MarkelZ/pygame-render

I can render 1000+ sprites at 60+ fps with shaders on my slow laptop. It's missing some documentation (for now), but hopefully the examples in the examples/ directory are self explanatory. Also, you can always just ask me directly.

OlaKenji commented 6 months ago

Hej, that's amazing! I ran your examples and seem to work fine. :D I will try to incorporate this into my project. I will let you know if I find anything or if there are issues.

OlaKenji commented 6 months ago

Hi again

I incorporated in your shader engine into the project (happy ville). For now, I simply only transformed the resulting screen into a texture and rendered with your default shader. It was very simple and easy to use! However, I notised that my FPS dropped to 1 if I rendered each sprite via the shader engine.

I looked through the code but didn't notice anything obvious, and your example 2 seem to be handling many sprites fine. Do you know what could be the reason? Is it texture_surface that is the bottle neck? The background spites are quite big in happy ville.

MarkelZ commented 6 months ago

Hey @OlaKenji

Can you open an issue on the repository of the shader engine so that other people with similar questions can see it too?

Yes, surface_to_texture is not meant to be used in every frame with large textures because the conversion from Surface to Texture is expensive. Instead, it's better not to use any pygame surfaces at all, and directly load the textures with load_texture and render them with render. You would need surface_to_texture only when you cannot avoid using pygame surfaces (for example because you need some specific pygame functionality).

I already checked out Happy Ville a while ago and it's really cool! I don't mind helping you increase the FPS but I would need more information about how you render stuff.