About rain... again...

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
User avatar
AshHouswares
Posts: 145
Joined: Fri Jun 03, 2022 11:31 am
Graphics Processor: Not Listed

About rain... again...

Post by AshHouswares »

I've tried multiple methods. None work. The only one that does work is one where I made an animated sprite of 512x512 and placed tons of them all over the map and the lag is atrocious, even on my high end windows 10 laptop. So I'm asking.

Is there a way to make a rain sprite constantly be in front of the player, so it at least LOOKS like its raining constantly? Or, alternatively, a script to make a kind of "RAIN EFFECT" appear in front of the player so it LOOKS like its raining? I say a script because obviously, I would want this to "switch off" when entering buildings and reactivate when leaving them.

Please help, this is driving me mental at this point.
Guest

Re: About rain... again...

Post by Guest »

You may be in luck. I recently had to put together a weather system for a project I've been helping a friend of mine with. Can't share it here just yet because it depends on a utility library I'm putting together that's not quite ready for public consumption yet, but once that's released I do plan on extracting the weather system from my friend's project as a usage example of some of the features. Feel free to have a look then (or just grab it outright if it suits your needs).
Magdiel012
Posts: 12
Joined: Wed Dec 21, 2022 10:59 am
Operating System Version (Optional): Windows 11
Graphics Processor: nVidia with Vulkan support

Re: About rain... again...

Post by Magdiel012 »

Guest wrote: Wed Dec 21, 2022 12:58 pm You may be in luck. I recently had to put together a weather system for a project I've been helping a friend of mine with. Can't share it here just yet because it depends on a utility library I'm putting together that's not quite ready for public consumption yet, but once that's released I do plan on extracting the weather system from my friend's project as a usage example of some of the features. Feel free to have a look then (or just grab it outright if it suits your needs).
(oops I would've edited this but I forgot to log in before posting lmao)

I should probably mention that I would heavily discourage simply putting a sprite in front of the player's view. The sprite will only look correct when viewed from whatever perspective the rain sprite is drawn from, so unless your map is meant to be played without vertical look rotation and you draw the sprite to be looked at straight forward, the effect will look jarring most of the time.

You could also look into making the effect as a post-process shader. I'm not all that familiar with the technicalities behind it (especially not in GZDoom), but theoretically you'd need to pass the player camera projection to the shader as uniforms so you can draw the rain from the correct perspective, and I couldn't tell you where that's accessed from (or if it's even exposed to ZScript). You'd also need to sample scene depth to make sure foreground objects occlude distant rain, but again, I haven't looked into shaders in GZDoom and couldn't tell you whether or not they let you access the depth pass.

I should also note that both of these solutions won't account for building interiors without a lot of custom work, and even then you'd have to make compromises.

(Got a little carried away, this next bit turned into a whole blog post. I've kinda been itching to talk about this for a while now, sorry.)

Since I can't show the solution I arrived at for my friend's project quite yet, I'll try to at least detail what my process was:

TL;DR I ported a triangulation library to ZScript to triangulate sectors with specific tags and wrote custom Thinkers to spawn rain drops from random points within the sector geometry. If that sounds daunting, it's because it was.

What I arrived at might seem like overkill for most, but my main design goal was near-frictionless usage at design time: it needed to Just Work™ from the map editor side, and be simple enough to customize from the scripting side. Since sectors already represent a convenient way to describe discrete regions of level architecture, I figured it'd be appropriate for the weather system to work off of sector data, and since UDMF allows for sectors to have multiple tags, I decided to use tags to mark sectors that the system should take into account. Then I had to figure out some way to get random points within each sector to spawn the rain from. At first I considered picking points within a bounding box surrounding the sector and discarding any that weren't within the sector's lines, but this only works well with relatively evenly-shaped sectors, and is especially bad for sectors with multiple faraway islands. I also considered sampling points from a circle, but that suffers from all the same issues. Eventually my research led me to triangle sampling: it turns out you can pick random points from within a triangle using barycentric coordinates. I can't quite remember where I got the algorithm from (think I even forgot to give credit in the source ;_;), but with that I just needed to find a way to triangulate the sectors' shape(s). Invalid geometry data may cause issues in this regard (polygons that aren't closed or that intersect themselves, for instance), but since this is meant to be used when authoring maps, I figured it could be avoided at design time.

Writing a triangulator from scratch is no small undertaking coming from no prior knowledge which is why I gave up within the first 2 days lol. There were many libraries I could've tried porting, but from what I could gather, something that output a constrained Delaunay triangulation would best suit the system I was trying to make (triangles respect input lines, allows for holes within shapes, more evenly-sized triangles, etc.). I ended up picking poly2tri because it does everything I needed it to do and the license for it is sufficiently permissive. But before I could port it, I needed to find a way to turn sector geometry data into something the triangulator could work with.

Since trying to debug this from within GZDoom was gonna take more work than actually getting the task done, I set up a little project in Godot (free open-source game engine) to test my logic as I went along and make sure it works before trying to port it over. Luckily, Godot supports C# scripting and there's already a C# port of poly2tri (and I'm generally pretty comfortable with the language), which made testing my own code that much easier. I took cues from this thread reply and UDB's level triangulation code (specifically the shape tree logic, by this point I had already taken care of the rest) to make a shape tracer that would loop through all the lines in a sector and sort them into shapes, then sort those into trees to find holes and nested shapes. The tracing logic isn't perfect: it skips non-closed lines nested within other shapes and there are a few edge cases where it fails to detect certain holes, but for the project's purposes it works well enough and the relevant shortcomings can be overcome at design time.

After confirming that the code I had could spawn things randomly inside a shape, I finally started porting thew whole thing. Honestly, this was the most frustrating part of the process. I was rather new to ZScript (specifically ZScript, I've been programming for a little bit) when I started going down this rabbit hole and downgrading from C# was painful. Lots of rewriting and desugaring the code to get it to work (I had to implement quicksort three separate times), but after that was done all that was left to do was write a little API to make using it more convenient and making the actual weather logic, which was considerably simpler. I wrote a custom Thinker class that would be given a sector to work with and pick random points from inside it using its triangulation to spawn weather particles over time, then I wrote an event handler to create a weather spawner for every sector with the tag I chose for weather effects when the level loads, and that was the bulk of the logic. After that, all that was left to do was expose parameters to customize the effect from scripts.

And after two-and-a-half weeks, it was finally done :)
[imgur]https://imgur.com/a/wlmNSgv[/imgur]

wait do imgur tags not work?

There's a good bit more I could say about optimization and other additions I made to it over time (the splashes were pretty recent), but I've been going for a little too long now I think :^).
Last edited by Magdiel012 on Wed Dec 21, 2022 5:00 pm, edited 4 times in total.

Return to “Scripting”