Pages

Showing posts with label rendering. Show all posts
Showing posts with label rendering. Show all posts

Sun Shafts & SSAO

 Added screen space sun shafts, based on this article from GPU Gems 3.





Also added basic SSAO(screen space ambient occlusion).  Right now it is just using the depth buffer.  For performance I will switch this over to using a downsampled depth buffer at some point in the future.  There are also some alternative methods that take into account surface normals that tend to generate more accurate results, so I might add one of those methods later.
Ambient Occlusion

Atmospheric Scattering



       Atmospheric scattering based on Eric Bruneton's Precomputed Atmospheric Scattering.

 I really like the look this algorithm gives, I'm only part way through implementing it so not everything is working, or at least as well as I'd like.

 His algorithm produces three colors, inscatter color, ground color, and sun color.  Although Bruton's sun color looks good in his screen shots, in the demo it looks rather bad; I believe the demo is an incomplete version.

 Part of the algorithm requires the distance from the viewer, here I am reconstructing based on the depth buffer, and to get this working I went ahead and implemented a proper deferred renderer, so yeah!

  Oh, and the first time I ran the atmospheric code this is what my planet looked like(precomputed table wasn't right )....

Deferred Texturing ?

  One method I tried, that didn't end up working very well, was deferred texturing for the terrain.

The terrain texture coordinates are based on its world coordinates and normal.  Using the GBuffer normal + depth buffer to reconstruct world position gave me what I needed.

 And while this worked and produced identical texture coordinates, the gradients were not always correct, resulting in some nasty looking aliasing anywhere that the depth buffer contained a large difference between adjacent pixels(because originally they were separate objects).

 My understanding is that the graphics card works on 2x2 pixels--

AB
CD

So the world coordinates are calculated in the four pixels, the difference between the adjacent pixels world coordinates is used as the derivative for MIP calculation.

But if pixel A was from a completely different mesh than pixel C, and 1000 meters closer to the camera, it ends up with really large derivatives and selects the lowest MIP--this is not what you want!

 So everything ends up with a blocky/pixelated outline that shimmers and looks just awful.

 If you passed down the derivative information perhaps you could work around it, but that is quite a large amount of extra data, and I didn't want to go down that route.

Occlusion Culling #1

(this is a very old post, I no longer use any of this)

 Recently I decided to try adding real occlusion system to my game.  There are a bunch of different ways to accomplish this, here are some common ones.

1) GPU occlusion queries
2) Software rendering for occlusion testing
3) Manual artist created portals and other similar systems(like Quake)

 #3 is a non-starter for me as I want a dynamic game world, and don't have artists to throw around.

 #1 I have tried before, but found that the inherit latency of CPU->GPU->CPU too large.  I tried cheating by issuing a query for each rendered object every frame, and simply not drawing in if it failed the query test from the previous frame, but this suffered from pop-in.

 #2 has become rather popular of late, and it is the method I decided to try this time.

 A software renderer could be implemented as either a rasterizer or a ray tracer, and since I already had support for ray casting into my scene, via Bullet,  I decided to try that first.

  I wrote a little program to generate depth map of the scene by casting rays through the physics system, it was trivial to parallelize it since each ray was independent of the others.

 Unfortunately performance was not good , as it turned out Bullet just wasn't fast enough to be ray casting 20,000+ rays each frame. I believe part of this is the fault of my levels which have far more objects than a typical game.



 So I went back on that idea and switched to rasterisation.  I stumbled across this post on devmaster by Nick, which was very helpful in getting a basic triangle rasterizer up and running.

 I am at the point now where I can rasterize the scene on the CPU and performance is overall much better than the previous ray tracing attempt.  I haven't even parrallelized or SSE'd it yet and it performs quite well(rendering ~50,000 triangles).


  For my terrain I am using convex hulls of each chunk, these typically use a small fraction of  the actual number of triangles that the rendered terrain contains. Unfortunately the generated hulls aren't exactly conservative(meaning they sometimes extend beyond the bounds of the source mesh), so I am certain I will see situations where the occlusion system says something is occluded when it really isn't...

 ...more on this later.

Geometry shader = BSOD?

 So I am rendering some points and wanted to quickly visualize them as billboards.  The geometry shader is a good way to do this so I wrote a GS to output a screen aligned triangle where each point would be.  This works-- mostly, except when I randomly get a nice blue screen of death while looking at the output.

      I wonder if I'm stressing the GS too much somehow.  While I am only outputting 3 verts for each incoming vert, I am rendering millions of points.  I've tried a few different variations of the shader and they all seem to eventually BSOD on me.

   Hard boot restart each time it happens, grrrr.