Finite Element Visualizer banner

Finite Element Visualizer

15 devlogs
57h 1m 56s

Updated Project: This new version has brought a lot of additional features such as: a PBR renderer, GPU solver, UI tweaks, meshing exporting, improved PSLG drawing, and Neumann boundary conditions.
Link to original project (started in SoM): https…

Updated Project: This new version has brought a lot of additional features such as: a PBR renderer, GPU solver, UI tweaks, meshing exporting, improved PSLG drawing, and Neumann boundary conditions.
Link to original project (started in SoM): https://summer.hackclub.com/projects/3232

Explore the time propagation of solutions to PDEs (partial differential equations) on surfaces in 3D space in this interactive sandbox! This project was written using C++ and OpenGL. The Finite Element Method was used to numerically solve these PDEs which requires using a lot of Linear Algebra in combination with some Multivariable Calculus.

Demo Repository

Loading README...

tvumcc

Shipped this project!

Hours: 57.03
Cookies: 🍪 1609
Multiplier: 28.21 cookies/hr

The second release of Finite Element Visualizer is done! This new version has brought a lot of additional features:

  • PBR Renderer: Meshes will now be shaded more realistically according to their environment, helping with depth perception a bit. This also includes a cool skybox to replace the previously gray background.
  • GPU Solver: An experimental implementation of the conjugate gradient method on compute shaders to speed up computation (if enabled). This is still a bit buggy on some systems.
  • UI Tweaks: Tooltips with explanations to make the UI slightly less daunting.
  • Mesh Exporting: Meshes can be exported to a .ply file to store mapped vertex colors and extruded vertex positions. These can then be loaded into Blender to make some cool renders!
  • PSLG Drawing Tweaks: Images can now be loaded into the scene so that you can trace over them in the PSLG draw mode.
  • Neumann Boundary Conditions: The option for selecting between Neumann and Dirichlet boundary conditions (both zeroed) now appears if the mesh has any boundary nodes.

It was a lot of fun revisiting a somewhat old project (I started this back in June 2025 at the start of Summer of Making 2025). This is by far the largest project I’ve ever built solo, based on both lines of code and hours spent.

tvumcc

Hello! I spent the time in this devlog trying to iron out bugs that arose when testing on Windows (I develop on Fedora). I think I fixed most of them. Besides that, I rewrote the README to reflect all the new things added. Below is a screenshot that I included on the README: Gray-Scott Reaction-Diffusion equation solved on a planar mesh in the shape of the Apple logo (mostly because it’s recognizable).

Attachment
0
tvumcc

I implemented a progress bar at startup since some assets (like the HDR image used for the PBR lighting) take a while to load and process. I also improved the first-time user experience by having the preset sphere mesh initialized at the start.

Attachment
0
tvumcc

I mostly just spent some time fixing (and sometimes failing to fix) minor bugs. I also reorganized a lot of my old shader code. I think next on the agenda is to try adding preconditioning to my GPU conjugate gradient method implementation, write missing documentation, and write an updated README. Below is just a GIF of a glossy cube I thought looked cool. (the quality is bad but I wanted it to autoplay on this page)

Attachment
0
tvumcc

I finished the physically based renderer by implementing specular image based lighting. This means that there are now reflections. Compared to how the renderer looked before (flat colors, no lighting, grey background), I’d say this a pretty big improvement.

Attachment
0
tvumcc

Just a quick thing I forgot to do earlier: I added the triangle mirroring thing that I had in the exporter, into the renderer. Now the mesh can appear as if it is volumetric. I was originally going to actually generate the geometry of mirroring but I ended up just writing all of it in a vertex shader. I was able to just reuse the normals from the normal compute shader I wrote earlier.

0
tvumcc

Hello! I started off image based lighting by making a class “EnvironmentMap”. So far, I have written code to convert the equirectangular image from a .hdr file into a cubemap and then render it in the main scene.

Attachment
0
tvumcc

I implemented physically based direct lighting by using the normals from the compute shader I wrote last devlog! Next, I will implement diffuse and specular image based lighting and have a little skybox which will replace the boring gray background that has been there since the beginning of the project.

Attachment
0
tvumcc

I wrote a compute shader to recalculate normals for smooth shading based on the extruded vertices. I ran into an issue with race conditions since different triangles being processed in parallel sometimes add normals simultaneously. To fix this, I just used atomics. Having these normals will allow me to implement lighting in the renderer.

Attachment
0
tvumcc

In this devlog I implemented the GPU solvers for the Advection-Diffusion and Gray-Scott Reaction Diffusion equations. Besides that, I mostly just fixed bugs I encountered while testing; most of them had to do with synchronization between the CPU and GPU. Now that this saga is basically over, I am going to shift gears to improving the 3D renderer with proper lighting, ambient occlusion (might make the ridges look cool), and maybe a skybox.

0
tvumcc

I spent so long debugging… programming for GPUs is not for the impatient.
Anyways, I finally got a (semi) working GPU implementation of the Conjugate Gradient Method with OpenGL compute shaders. What this means is that (hopefully) the simulation will be able to run on larger meshes much faster due to the parallel computing offered by GPUs. Below is a video of the Wave Equation solved on the surface of a torus using this new implementation.

0
tvumcc

It’s been a while! I started work on implementing conjugate gradient method (basically an iterative linear system of equations solver) for the GPU using compute shaders. While doing so, I realized that my current code structure (for the finite element method solver side of things) is pretty coupled and convoluted. So, I basically spent most of the time in this devlog experimenting with different ways to structure everything. The image below shows the structure I am currently settled on.

Hopefully I actually have some new visuals in my project next time around!

Attachment
0
tvumcc

I did a lot of things over this 6 hour dev log:

  • Added Neumann Boundary conditions so now the boundary edges aren’t fixed to 0 (see slide 1)
  • I did some more tweaks to the UI
  • I started work on the GPU implementation of the conjugate gradient method by writing a dot product procedure in a compute shader using parallel reduction (see slide 2). What’s interesting is that summing using parallel reduction is actually better for floating point precision than just summing serially.

From here, I will continue working on the GPU implementation of conjugate gradient method. I am interested to see how much of a speed up will actually be gained when compared to the CPU implementation.

Attachment
Attachment
0
tvumcc

I spent most of my time revamping the UI. I changed things like button sizes and labels and added the option to select from preset meshes. I do still want to spend time on refining the UI to make sure users fully understand the flow of the app’s usage.
Image 1: General UI update
Image 2: Preset Meshes Selection List (UI is probably going to change)

Attachment
Attachment
0
tvumcc

I wrote some code to export the meshes that get generated to .obj and .ply files! Based on the value of the solution at each node (3D vertex), that vertex is extruded along its normal vector and given a color based on a color map (I’m using Viridis right now). The image below is an export of the Gray-Scott Reaction-Diffusion equations solved on the surface of a cube (slide 1) and a skull mesh (slide 2), both rendered in Blender.

Attachment
Attachment
0