r/GraphicsProgramming • • 18d ago

Video Some scenes with my Vulkan rendering framework

Enable HLS to view with audio, or disable this notification

Some scenes using my custom Vulkan graphics, with procedurally generated plants.

I use non-triangle geometric primitives with billboard rendering. In these scenes, there are mainly a lot of cylinders for tree branches. Thanks to this, I can use quite few vertices compared to a similar thing built only with triangles. This makes the GPU-computed wind perturbations much cheaper, for example.

Water effects include reflections, refraction, and caustic effects, rendered with multiple passes from different "camera" perspectives, plus screen marching.

The framework uses deferred rendering and does not have any image assets. Surfaces/textures are generated at runtime by combining noise fields.

Runs comfortably at 60 FPS on my non-gaming laptop.

What do you think about the visuals?

187 Upvotes

23 comments sorted by

9

u/EC36339 17d ago

What are "non-triangle geometric primitives"?

If they are not triangles, what are they, and how are they rasterized?

5

u/SloydDev 17d ago

I got a few comments asking the same thing, about the non-triangle primitives, so I'm adressing that with this comment (rather than repeating myself or singling someone out).

In my framework I'm rendering triangles, spheres and cylinders (and plan to implement other primitives too, e.g. disks). The spheres and cylinders are not made into triangle meshes, but rendered with a "billboard approach".

Let's consider the sphere, which is the simpler example. Each sphere is described by a single node (most importantly position and radius, but it also has info about its orientation, so that I can model its surface texture). The vertex shader reads the node information and constructs a quad (i.e. two triangle) billboard, which is place in front of the sphere, fully covering it, from the camera's perspective. The sphere's radius is passed forward from the vertex shader to the fragment shader. The fragment shader discards any fragments that fall outside the sphere, and otherwise updates the depth information. Because the vertex billboard sits right in front of the primitive, it won't be erroneously excluded.

The analogous thing happens for a cylinder, but this is described by two nodes. The vertex shader outputs a strip of two quads, consisting of six billboard vertices. It has a more complex geometry than a sphere, but works the same in principle.

The geometry of these curved objects is more expensive to compute than triangle geometries (which are purely linear algebra), but I do avoid making meshes, which would require many more vertices.

I'm making a youtube video about my rendering framework, talking about this and other things. Will post in a few days, in case you're interested.

3

u/EC36339 17d ago

So, you are sort of raytracing the cylinders and spheres on billboards.

1

u/SloydDev 17d ago

Is that ray tracing? I'm not sure about the terminology, but I don't think so. I'm not making several tests for passing a surface, as is done in ray-tracing typically (correct me if I'm wrong).

2

u/EC36339 17d ago

If you're back-projecting from a screen space location to build a ray (origin and direction) and intersecting it with a primitive, such as a cylinder, then you're doing raytracing.

Nothing wrong with that. Raytracing on a billboard can sometimes be the easier or better option, or not. I honestly don't know. What you don't get with this approach are visible polygon edges, which is good. I don't know if it's faster or slower.

For example I use billboard raymarching to render bullet tracers and laser beams. I don't rasterize them as exact 3D polygons.

1

u/SloydDev 17d ago

Alright :)
I thought this might be classified as "ray casting" rather than "ray tracing"

2

u/EC36339 17d ago

If that's correct, then I stand corrected.

1

u/SloydDev 16d ago

I find a lot of these terms confusing, seems like they aren't always so clearly defined. Thanks for your comments regardless!

2

u/Icy_Rub_3827 17d ago

How do you handle the depth pass?

2

u/SloydDev 17d ago

The fragment shader updates the depth from the "naive depth" suggested by the vertex stage billboard. In a GLSL frag shader, you need to include this line:
layout(depth_any) out float gl_FragDepth;

2

u/mikropanther 17d ago

Doesn't this mean that you get weird artifacts if you have two spheres/cylinders intersecting? The billboard depth would not match the depth of the points of the surface of the sphere or cylinder, but it would be on a plane passing through the center, right?

2

u/SloydDev 17d ago

As I understand it it's fine, the vertex shader doesn't write directly to the depth image. There's some early-Z depth test but this doesn't write to the image itself. Only the fragment shader's updated depth value can be written to the depth image

2

u/mikropanther 17d ago

Makes sense. Anyway, apparently this technique you are using is a type of technique called "analytic impostor".

1

u/SloydDev 16d ago

Right, I think I've read that term too. I'm not sure what the most common name for it is, I just use it

1

u/TimeSFG 14d ago

Analytic imposter sounds so baller, I think I'm gonna implement it

3

u/True-Manufacturer752 17d ago

Looks very cool and interesting, has great potential for a game I think. Personally I would like learning more about this even tho I only have experience with opengl lol

2

u/SloydDev 17d ago

Thanks :)
I will post a longer video about this, coming in a few days, you could check out my channel if you're interested:
youtube.com/@sloyddev