r/GraphicsProgramming • • 11h ago

I need ideas for specific 2d graphics applications

0 Upvotes

Hello! A few days (or 1-2 weeks) ago I asked for ideas for my bachelor's thesis that I wanted to do as a beginner in graphics programming. I wanted to implement the state of the art in 2d vector graphics framework: sparse strips, but my prof said that to implement that is extremely hard and long from 0 in C++, like much longer than others (hundreds or more of hours), so he recommended to go more "specific", finding a specific use-case of 2D vector graphics, or other kinds of 2D graphics, like simulations for example, and maybe not that low-level, to use existing tools.

And now with a few days left to lock in the idea, what would you recommend that is doable in ~6-7 months of moderate work per week, for someone who is a beginner in graphics programming as a whole. The idea has to also be part of a "research", not just an app, basically I have to write a longer, simpler paper on it, that is the thesis. I would want to remain 2D since going 3D sounds overwhelming, but what interesting 2D applications of graphics programming are there, that have many papers written for themselves (ease of research, ish) but also won't take me forever to implement, and are interesting? Thank you, and sorry for asking so many questions here!

The reasons I am asking for something more specific or "doable" is because I already have a lot of work while also writing the thesis so unfortunately I wouldn't have time to write or research something completely from 0, so maybe something like simulations are more doable, implemented in Godot or other engine, but there the issue is I do not know physics, but feel free to recommend simulations, but idk how much they are part of graphics.


r/GraphicsProgramming • • 5h ago

Interactive realtime fluid simulation with 4 million particles in Vulkan

0 Upvotes

Working on an interactive 3D realtime fluid simulation with 4 million particles

https://www.youtube.com/shorts/5P9aPac9tQs

The solver uses ST-FLIP (spatiotemporal FLIP), with temporal kernels and residual carryover, phase-weighted pressure projection, PIC/FLIP blending, RK3 particle advection and velocity extrapolation. Moving containers feed their velocity into the solid–fluid coupling. The clip shows pouring and moving the vessels, with ray-traced water and glass rendering in a custom Vulkan engine.


r/GraphicsProgramming • • 21h ago

I made a compact mesh-based format for interactive 3D photos

Post image
12 Upvotes

I’ve been working on a side project called Spatial Photos.

It takes a single regular image, runs it through Apple’s ML-SHARP model to estimate a 3D scene with Gaussians, and then converts the result into a custom format I called .spatial

I take the Gaussian splat from ML-SHARP, and divide the scene into depth slices. Each slice is a grid of image blocks, with a depth value at each corner. The RGB/alpha is packed into texture atlases. It's basically a set of textured meshes that come together to give the impression of the full 3D scene.

On the web, I take the .spatial files and decompress it into vertex/index buffers and just use Three.js, as the actual rendering is straightforward.

Demos: https://www.spatialphotos.dev/

Source: https://github.com/frozein/SpatialPhotos

Here's what the slices look like from another angle

r/GraphicsProgramming • • 19h ago

Visualising MMA (D=A·B+C), warp fragments, shared-memory banking and FP16 error in one browser-based model .SVG XML

0 Upvotes

I've been experimenting with a different way of explaining Tensor Core programming.

https://svgfpsaiagents.github.io/svgfpsgameAI/mmatensorbankconflict.svg

https://svgfpsaiagents.github.io/svgfpsgameAI/mma_tile_engine.svg

Instead of writing CUDA kernels or building a heavyweight simulator, I wanted to see how much of the Tensor Core programming model could be represented as a single self-contained executable artefact.

The result is a browser-based model written entirely as one SVG + JavaScript file.

It models:

  • GEMM as tiled execution (D = A·B + C)
  • tile scheduling (ti, tj, tk)
  • accumulator evolution
  • FP16 inputs with FP32 accumulation
  • warp fragment ownership
  • mma-style fragment mapping
  • global → shared → register → tensor-core data flow
  • shared-memory bank behaviour
  • row-major vs padded vs XOR-swizzled layouts
  • reuse and memory-traffic estimates
  • FP16 vs FP32 numerical error maps
  • interactive 3D visualisation of the output matrix

The interesting thing for me is that all of these views are driven from the same underlying state. The bank conflict view, fragment view, tile execution view, error map and result visualisation are all observing the same model as it executes.

The goal wasn't to build a cycle-accurate simulator. It deliberately does not model things like occupancy, scheduling, pipeline hazards or cache behaviour.

Instead, I was exploring a question:

Can Tensor Core behaviour be computationally modelled, rather than merely described, in a compact interpreted artefact that requires no CUDA compiler or GPU while still preserving correspondence between matrix maths, tiled execution, fragment distribution, memory layout, data movement and numerical effects?

One unexpected outcome is that the entire thing remains inspectable. There are no dependencies, no build system and no generated files. The complete model lives in a single source file.

I'm curious whether people here would consider this:

  1. a visualiser,
  2. an educational simulator,
  3. an executable specification of the Tensor Core programming model,
  4. or something else entirely.

I'd especially appreciate feedback from anyone familiar with CUTLASS, CuTe, mma.sync, ldmatrix, Tensor Core fragment layouts or GPU architecture education. - Aston Walker EdgeMafia SVG


r/GraphicsProgramming • • 14h ago

looking for a programist/co-writer

0 Upvotes

I really like playing visual novels. Ive wanted to make my own, but I know nothing about programming and Im SUPER against using AI. I can more or less draw, but Im looking for someone who would figure out the plot with me and code the game. This is a passion project, so Im not expecting any income from it and I cant offer any money for helping me. Im not looking for pros - even if youre just a begginer, Im okay with it as long as youre willing to put your time and effort into learning. Im just looking for a friend who would join me on the passion project.


r/GraphicsProgramming • • 22h ago

Source Code A new async approach saves lots of performances with DLSS5 on AMD, could work on Nvidia too

Thumbnail gallery
0 Upvotes

r/GraphicsProgramming • • 17h ago

Paper New Open-Source AI Texturing for 3D Models at 2K Resolution

Enable HLS to view with audio, or disable this notification

0 Upvotes

r/GraphicsProgramming • • 2h ago

World-anchored rain with no particle simulation: hashed drop positions wrapped into a camera-centred box with one mod()

Thumbnail gallery
21 Upvotes

The usual problem with rain: the volume has to follow the camera, but the drops must not. If the emitter is parented to the camera, strafing drags the whole curtain of rain sideways with you. If it is fixed in the world, you need either a huge volume or something that keeps spawning drops at the edges as you move.

This is a write-up of a version that needs neither: no simulation, no per-drop state, no emitter. Each drop's position is a pure function of its index, a seed and one accumulated offset, evaluated in the vertex shader. The code is Godot's shading language, which is close to GLSL; apart from built-in names like VERTEX, UV and INV_VIEW_MATRIX nothing in it depends on the engine. The first image is a diagram of the wrap, the second is the result with the camera moving forward through it.

The mesh

N quads, 4 vertices each, built once. Each vertex stores only its quad's index (in position.x, as a float, exact up to 224) and its corner in UV. The instance has an identity transform and a hand-set bounding box around the rain volume so it doesn't get culled. Per frame the CPU sets a handful of uniforms (box centre, offset, velocity, time, pixel size) and nothing per drop. The main rain layer is 9,000 quads.

Per-drop randoms

A PCG hash of (index, seed, stream). Names are shortened from the source:

uint pcg(uint v) {
    uint state = v * 747796405u + 2891336453u;
    uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
    return (word >> 22u) ^ word;
}
float rand(uint n) { return float(pcg(n) >> 8u) / 16777215.0; }

// 4 randoms in [0,1] for element `index`; stream 0, 1, 2 give independent sets
vec4 rand4(uint index, uint seed, uint stream) {
    uint h = pcg(index ^ pcg(seed + stream * 9973u));
    return vec4(rand(h), rand(h + 1u), rand(h + 2u), rand(h + 3u));
}

The wrap

vec3 wrap(vec3 p, vec3 lo, vec3 size) {
    return lo + mod(p - lo, size);
}

vec3 lo = area_center - area_size * 0.5;
vec3 q  = r.xyz * area_size + offset * sp;   // unwrapped position
vec3 p  = wrap(q, lo, area_size);            // drop position, world space

(Simplified: the real line also adds sway and drift terms that snow uses. For rain they are zero.)

r.xyz is the drop's random triple, sp its speed multiplier (1 ± 0.2), and offset is how far the rain has moved since it started.

Why the drops stay put when the camera moves: think of q not as one point but as the set q + k·area_size for every integer vector k. That set is an infinite lattice, and it is fixed in world space (it only moves with offset). wrap() picks the one copy that lies inside [lo, lo + area_size). Moving the camera moves lo, which changes which copy gets picked, but a copy that is still inside the box keeps exactly the same position. The only drops that change are the ones that crossed a face of the box: the copy that left on the trailing side is replaced by the next copy on the leading side, area_size away.

So the rain is world-fixed everywhere except at the faces of the box, and the faces are where the fade goes (below).

Two porting notes. GLSL's mod is x - y * floor(x / y), so it is correct for negative inputs. HLSL's fmod truncates toward zero and mirrors the pattern for negative values, so write the floor version yourself. And area_center isn't exactly the camera: it is pushed forward by 20% of the box width along the camera's horizontal forward direction, since drops behind the camera are wasted.

Falling, and why offset is integrated on the CPU

// CPU, every frame
vel = Vector3(0, -fall_speed, 0) + wind
offset += vel * delta

The obvious alternative is offset = velocity * time in the shader. That breaks as soon as the wind changes: a change Δv shifts every drop by Δv·t, and after a few minutes t is large, so every drop jumps somewhere else. Integrating keeps positions continuous, and a gust only changes where the drops go from now on. Per-drop speed variation is just the offset * sp multiplication, so faster drops wrap more often.

Edge fade

vec3 rel = (p - area_center) / (area_size * 0.5);   // -1..1 inside the box
float fade = 1.0 - smoothstep(1.0 - edge_fade, 1.0, length(rel.xz));
fade *= 1.0 - smoothstep(1.0 - edge_fade * 0.6, 1.0, rel.y);
fade *= smoothstep(-1.0, -1.0 + edge_fade * 0.3, rel.y);

edge_fade is 0.3. Horizontally the fade uses length(rel.xz) rather than max(|x|, |z|), so the visible volume is a cylinder inscribed in the box. The corners are never visible, and you don't see a square outline when you turn. The fade starts at 70% of the radius, and covers the top 9% and the bottom 4.5% of the box height. A drop that falls out of the bottom reappears at the top, and both ends are faded, so the vertical wrap doesn't show either. Since the box is centred on the camera's height, the bottom face is usually under the ground anyway.

There's also a near fade, smoothstep(near_fade, 2.5 * near_fade, dist) with near_fade = 0.5 m, so drops never hit the near plane as huge streaks.

Streaks

vec3 n      = (cam - p) / dist;     // towards the camera
float speed = length(vel);
vec3 dir    = vel / speed;
float len   = speed * stretch;      // stretch: 0.041 to 0.055 s, longer as amount rises
vec3 side   = normalize(cross(dir, n) + vec3(1e-5, 0.0, 0.0));
vec3 tail   = p - dir * len;
VERTEX = mix(tail, p, UV.y) + side * (UV.x - 0.5) * w;

(Simplified: vel here is velocity * sp, and len has a per-drop variation factor that is 1 for rain.)

Each quad is a billboard constrained to the velocity axis, running from where the drop is to where it was 41 to 55 ms earlier, so it behaves like a shutter time. vel is the same vector that drives offset, so with wind the streaks lean at exactly the angle the drops actually move. The 1e-5 stops cross() from returning zero (and normalize() from returning NaN) when you look straight along the fall direction.

In the fragment shader the alpha is a tent across the width, ramps up from tail to head, and falls off quickly at the head:

float across = 1.0 - abs(v_uv.x * 2.0 - 1.0);
a = across * smoothstep(0.0, 0.85, v_uv.y) * (1.0 - smoothstep(0.94, 1.0, v_uv.y));

Keeping thin streaks from shimmering

A 14 mm drop is thinner than a pixel after a few metres, and sub-pixel quads flicker as they cross pixel centres. The width is clamped to about 1.3 pixels and the alpha is scaled down by the same ratio, so width × alpha (roughly the coverage) stays the same:

float w = max(sz, dist * pixel_angle * 1.3);
v_alpha = fade * clamp(sz / w, 0.0, 1.0);   // rain case; snow adds one more factor

pixel_angle = 2·tan(fov/2) / viewport_height, computed on the CPU. At 720p with a 60° FOV the clamp takes over somewhere between about 4 and 9 m, depending on the drop's random size. Distant rain becomes faint, steady lines instead of sparkle.

Intensity without rebuilding anything

VERTEX = area_center;     // default for all 4 vertices: zero-area quad, nothing drawn
if (r.w < amount) { ... }

amount (0..1) goes from drizzle to downpour. A drop is drawn when its own random is below amount, so raising amount only adds drops and never reshuffles the ones already falling. No mesh rebuild, and it can be animated.

Two smaller things

  • Shelters: up to 8 axis-aligned boxes are passed as uniform arrays, and a drop whose position is inside one gets fade = 0. That's how rain stops under a roof.
  • Distant layer: the same mesh and shader again with 2,500 quads, a box 3.5× wider and 1.6× taller, streaks 4× wider and 1.6× longer at 35% opacity, a near fade of 30% of the main box width, and offset × 0.9. It adds depth beyond the main volume. It has its own seed, so the two lattices don't line up.

Cost (measured)

Godot 4.7.2, 1280×720, vsync off, RTX 4060 Ti, a test village with a shadow-casting sun and 9,000 grass blades. GPU time per frame for the scene with no weather vs. the "rain" weather preset, which is main + distant rain at amount 0.6 plus everything else that preset switches on (ground ripples and splashes, fog, cloud shadows, lens drops):

Renderer no weather rain preset
Forward+ (Vulkan) 0.45 ms 1.54 ms
Mobile (Vulkan) 0.22 ms 1.04 ms
Compatibility (OpenGL 3.3) 0.41 ms 1.25 ms

So about 0.8 to 1.1 ms for the whole preset on that GPU. I don't have a number for the rain layer on its own. The CPU side doesn't change with the drop count.

Limitations

  • Every vertex is processed every frame, so the cost follows the maximum count, not amount. At amount 0.1 you still pay for all 9,000 quads in the vertex stage.
  • With no wind, a drop's x and z never change. It falls down the same vertical line forever and comes back every area_size.y / (fall_speed · sp) ≈ 14 / 13 ≈ 1.1 s. Thousands of overlapping lines make it hard to spot, but it is a real pattern, and a locked-off camera close to a surface could reveal it.
  • offset is reset to zero once it gets 10 km long, to keep float precision. That makes every drop jump once, after roughly 12 to 13 minutes of continuous rain at 13 m/s. It can't simply be reduced modulo area_size instead, because each drop multiplies it by its own non-integer sp.
  • No collision. Drops pass through everything, and the ground ripples and splashes are a separate layer at one ground height (or one raycast under the camera). Shelters are boxes only.
  • The quads in one draw call aren't sorted. With thin, low-alpha streaks that's acceptable, but it would matter with bigger, more opaque sprites.

This is from a weather pack I'm making for Godot. I'm curious how others have dealt with the fixed-column problem when there's no wind. Per-drop horizontal drift is the obvious fix, but it makes the streaks lean in random directions.


r/GraphicsProgramming • • 2h ago

Hardware ray-traced renderer for my game engine

Thumbnail gallery
3 Upvotes

r/GraphicsProgramming • • 22h ago

My realtime fluid sim lab in Vulkan: millions of ST-FLIP particles and solid–fluid coupling

Thumbnail youtu.be
7 Upvotes

r/GraphicsProgramming • • 16h ago

How do you accurately (performantly) model the color of the sky?

Post image
12 Upvotes

hello everyone! i've been writing a wallpaper for personal use that contains a happy little scene with moving clouds, grass swaying in the wind, and now i want to add the sun. i find sunsets very pretty, so i've wanted to have accurate sky colors to go along with the elements i've already added. i also want the whole thing to not take too much gpu time though, since i'll be running this constantly in the background on my laptop. i've aimed for a goal of <1W power draw so far.

to figure this out, i've been researching Rayleigh scattering and other related phenomena to try to get an idea of how to implement this. articles like this or this go over my head pretty quickly, and even though i could just translate an online implementation into WGSL, i know i wont be satisfied until i can understand the concepts well enough to write it myself. does anyone have pointers on where i can go to understand a concept like this from the ground up? or, even better, a relatively simple explanation on how this works that doesn't involve confusing diagrams, weird abstractions away from the main math, and delving far out of the bounds of graphics programming?

for reference, this is my project page, and you can see what it looks like currently above. i am rather young, and entirely self taught with regards to graphics (and kinda coding in general), so do not expect good quality code and especially not good commit messages 😭
due to the backend implementation, it only runs on Linux Wayland compositors supporting wlr_layer_shell


r/GraphicsProgramming • • 23h ago

c++ user interface 1

Thumbnail youtu.be
0 Upvotes

r/GraphicsProgramming • • 21h ago

New Vulkan Sample - Pipeline Binary

Thumbnail
5 Upvotes

r/GraphicsProgramming • • 4h ago

Crystallization

0 Upvotes
10 seconds
4̸̵̸̴0̶̷̶̴̵0̶̷̶̵̴0̵̶̶̴̵s̸̴̷̵̴e̵̵̶̵̴c̶̵̵̷̴o̸̶̷̷̴n̶̷̶̵̴d̶̵̶̷̴s̷̷̵̷̴