Skip to content

Optimised line intersection by adding two simple prechecks.#14

Open
marmottchen wants to merge 1 commit into
MarkelZ:mainfrom
marmottchen:optimising
Open

Optimised line intersection by adding two simple prechecks.#14
marmottchen wants to merge 1 commit into
MarkelZ:mainfrom
marmottchen:optimising

Conversation

@marmottchen

Copy link
Copy Markdown

I added two simple checks to the line intersection function.
This avoids calculating intersections with edges that arent in the minimal rectangle containing fragmentTexCoord and lightPos.

The change should make the algorithm faster, altho I dont know how to test that.

@MarkelZ

MarkelZ commented Oct 17, 2024

Copy link
Copy Markdown
Owner

Hi @marmottchen! Thank you very much!! I created a script for benchmarking the code, here. Somehow, I found that the code with the two checks is a bit slower than the old version. Look at the outputs below. Avg. mspt means how many milliseconds it takes to render one frame on average.

My guess is that since the values calculated for the checks are not used later in the function, we ultimately lose more time than we save. Anyway, I still think doing the two checks is smart, but maybe we need to do this strategically? Any ideas?

Btw, if you try to run the benchmarks you will probably get the error _moderngl.Error: out of range offset = 0 or size = 6400. You need this fix (it just allocates more memory).

OLD code
======== Benchmark 0 ========
lights: 10, hulls: 10, vertices per hull: 4
running...
Avg. mspt: 0.7299156188964844

======== Benchmark 1 ========
lights: 200, hulls: 1, vertices per hull: 3
running...
Avg. mspt: 4.665932655334473

======== Benchmark 2 ========
lights: 10, hulls: 200, vertices per hull: 4
running...
Avg. mspt: 7.464873790740967

======== Benchmark 3 ========
lights: 200, hulls: 200, vertices per hull: 4
running...
Avg. mspt: 133.593111038208



NEW code
======== Benchmark 0 ========
lights: 10, hulls: 10, vertices per hull: 4
running...
Avg. mspt: 0.7444717884063721

======== Benchmark 1 ========                                                                 
lights: 200, hulls: 1, vertices per hull: 3                                                   
running...                                                                                    
Avg. mspt: 4.6094441413879395                                                                 
                                                                                              
======== Benchmark 2 ========                                                                 
lights: 10, hulls: 200, vertices per hull: 4                                                  
running...                                                                                    
Avg. mspt: 7.780803839365642                                                                  
                                                                                              
======== Benchmark 3 ========                                                                 
lights: 200, hulls: 200, vertices per hull: 4                                                 
running...                                                                                    
Avg. mspt: 139.31488752365112 

@marmottchen

Copy link
Copy Markdown
Author

My idea was to eliminate edges that are clearly not going to intersect by observing the rectangles for which they are the diagonals. Like boxes around the edges.
I guess the original calculation isnt expensive enough for this to make a difference tho.

We could try the same idea a step higher up with the hulls.
I am thinking that when defining a hull, we calculate the bounding rectangle and save it as another attribute.
Then when we do checks, before checking the edges of a hull, we check against the bounding box of the light edge.

I can try to adapt the code on the weekend, altho I dont know how to give the shader the additional hull information.
Could you maybe explain how one would go about giving the shader an additional 4 values per hull ?

@MarkelZ

MarkelZ commented Oct 19, 2024

Copy link
Copy Markdown
Owner

That seems like a great idea. There's one catch, hull data can change from frame to frame, because it's useful to have movable hulls in a game. So, we need to compute the bounding boxes every frame. This may be worth it tho, especially if we cache the bounding boxes, since we can expect that most hulls won't change.

For sending this data to the shader, first you need to create an SSBO uniform in the light shader. Just take a look at how hullVSSBO is defined. It's the list of hull vertex coordinates, and it is an array of floats (instead of vector2) because it is a flattened list. I assume that you can just define two more such arrays for the bounding boxes, one for the lower bounds and another for the upper bounds.

Then, you need to go to LightingEngine and reserve enough memory for the SSBOs you just defined. You should do this in the _create_ssbos function, I think it should be 8*max_num_hulls bytes for each SSBO. It's very similar to the other lines of code in that function.

Lastly, to send the bounding box data in each frame, simply do as in function _send_hull_data of the LightingEngine.

If you are having trouble implementing this, just ping me and I'll be happy to help. Also, no need to implement the caching yet, we can do that later. Excited to see what you come up with :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants