Monday, April 30, 2012

Up Close

Hmm...maybe those black lines were actually part of the geometry.  Up close, the ship looks good, and I can see how one might mistake the occlusion caused by thin plates for artifacts.  Well, I'll keep my fingers crossed.


Smooth

As I approach completion of the rendering component of the project, I'm going to need to make sure that everything is really polished and well-done.  Right now, the system is good, but there are still some noticeable problems.  I have been avoiding these until now because I usually looked at fairly noisy images.

After 20 minutes of rendering, however, the problems become apparent, as the rest of the image smooths out:


There are two distinct black-ish lines on the ship that I can't figure out.  On top of that, there's the ever-present problem of discontinuities near the edge.  At this quality, the discontinuous normals are also very prominent, and the lack of texture is pretty detracting.

There's still a lot of refining that needs to be done before this tracer will be ready to produce a professional-quality image like those that PBRT yields, but I have faith that it'll get there!

Glossy


Immersed

I really like the new participating media system.  The fixed math works wonders!  Here's the classic test scene immersed in a cylinder of gas:


I really love how much that lower light propagates through the gas - this is exactly the effect that I want the ship's mining beam to have in my render.  I want the surrounding gas to be brightly-lit and saturated with color.  Looks like this system will be perfect for just that!

MLT & Gas

First attempt at MLT and scattering.  Actually, it really has nothing to do with MLT...I should say first attempt as scattering in CUDA, and massive convergence speedups thanks to the ever-magical MLT!

This time I actually read a proper paper on the subject rather than hacking the math, so the scattering looks much better.  I only let this one render for a minute or so:


To be honest, the MLT-style low-frequency noise gives the gas a really nice wispy effect!  Much preferred over high-frequency noise.  Hmm...now how do I get that wispy effect with a density function?

Saturday, April 28, 2012

Five Minutes

Go an awfully long way with MLT :)


[loving that resolution]

High Res

Equipped with MLT, I'm now able to view my scenes in more detail than ever before with only a few minutes of waiting time:


There are several conclusions that I can draw from this high-res shot:

  • My MLT implementation isn't normalized (I knew this, I was just using an ad-hoc value, but I'll need to compute the real average)
  • Those Voronoi asteroids really are going to cause problems with the discontinuous normals
  • There's still an unknown problem causing triangles viewed from the side to appear black in some cases (this is visible at the edges of certain parts of the ship).  This concerns me a lot, as I'm not sure whether it's a problem with my tracer, or whether the normals of the ship are just bad.  I'm tempted to think the latter, since bumping up the resolution seems to fix things.

Killing Fireflies

The cure for MLT fireflies is actually easy: limit the maximal number of sequential mutation rejections.  I saw this while reading the PBRT Metropolis code and, by chance, decided to give it a shot.  Sure enough, it turns out that almost all of the fireflies that I was observing were due to the path getting "stuck" in bright areas and rejecting a lot of mutations in a row.

Here's a comparison.  The image below was given 30 seconds to render, and has no rejection limit:


Here's the same scene, also given 30 seconds to render, with a rejection limit of 32:


Notice that pretty much all of the fireflies disappeared!  For reference, here's the same scene given 30 seconds of brute-force path tracing:


The difference between MLT and brute-force in this instance actually isn't that profound.  Although the MLT shots still look better, the difference really becomes evident after longer running times, when path tracing continues to waste time on unimportant areas, while MLT continues to allocate samples intelligently - the gap grows ever wider.

MLT!!!

I did it :) After so many hours of reading ridiculously-overly-complicated papers and failing so hard at the math, I finally got it right.

Here are some results.  The classic test scene box, this time with only 3000 spp (which looks substantially smoother than the 5000 spp brute-force version that I had been using as reference):


Here's the ship:


And finally, something that the tracer never could have done in a reasonable amount of time without MLT:


That's using only ~100 spp...not bad at all!

It's not perfect yet...in particular, there's an unusual abundance of fireflies.  Although, I have observed the same problem with PBRT's implementation...maybe this is just a fact of the algorithm.  Still, I'm sure the results can be further smoothed out.

I'm pleased to say, however, that I'm finally convinced that my renderer is better than PBRT for my purposes.  It's faster, and now it's also (almost) as smart, which means, overall, it's a good bit faster.

I still have the fortune that I got from a fortune cookie last Sunday sitting on my desk...it says "luck will soon come your way." I was hoping that it was referring to my rendering project.  Sure enough, it was.

Thursday, April 26, 2012

MLT

I want so badly to be able to understand and implement Metropolis Light Transport.  I'm trying, but it's so dense...I really hope I'll be able to understand it after enough reading :/ I think it would make a huge difference in image quality.

Wednesday, April 25, 2012

Boxes

Ah, path tracing...you make everything look so beautiful.  Even boxes.


Tuesday, April 24, 2012

5000

Finally, I'm able to render a 5000 spp image in a reasonable amount of time.  Here's my class test scene at 5000 spp, rendered in ~8 minutes.


For reference, smallpt (http://www.kevinbeason.com/smallpt/), which is similar to my tracer in that it only uses brute-force path tracing, renders the Cornell Box scene at 5000 spp in 124 minutes on the CPU.  Note that the resolution is ~2.5x my resolution, so taking that into account, I'm still about 6x faster, but my scene is obviously way more complex.  I mean, that's not really a fair comparison by any stretch of the imagination, but at least it proves that I'm not totally crazy to pursue path tracing on the GPU.

Hit the Mark!!!

Today I achieved my performance goal of 10fps on the medium-quality ship scene.  It marks a huge improvement over the first path tracer, which would have attained about 0.5fps.  Not only that, but it marks a significant improvement over the highly-optimized GLSL tracer that was my state-of-the-art only two days ago, and was not even half as fast (4.5fps).

Most of my recent performance gains were from various tweaks to CUDA, not so much changes to the path tracing code, although I did gain a little speed from caching first bounces (view-ray intersections).

I think I'm finally able to say that my path tracer is good enough for competition use!  I still need to add texturing/normal mapping/a host of other things, but none of that should be too hard.  Soon I'll be returning to the procedural content part of this project to work on the scene!

Exciting times :)

Monday, April 23, 2012

CUDA is Fast!

So far, the new CUDA tracer is ~60-70% faster than the old one!  That makes me very happy.  I've almost hit my goal of 10 fps on the medium-quality ship scene.  Now, however, I'm equipped with much better profiling tools (thanks, NVIDIA!!!), and a generally-better idea of how to proceed with optimization.  As always, I'm hopeful :)

Here are two familiar shots, this time rendered with CUDA...less noise in the same amount of time!



First Render in CUDA

Everybody's favorite shiny balls, this time rendered on everybody's favorite new GPGPU toy.  I haven't ported dynamic scenes or anything fancy yet, just spheres at this point.  Right now, it's a good bit slower than the GLSL tracer was at this stage, but that's not really saying anything, since the only thing that's being used right now is constant memory.  Let's hope that things will get better when the real renders begin...


Something Smells Like CUDA...

If I can't beat them, I'll join them.  In my final (and probably last) attempt to find performance, I'm going to do the insane: I'm going to learn CUDA in a few days solely for the purpose of writing this path tracer.  Maybe I'll find the performance I'm looking for, maybe not.  As if the idea of writing a path tracer wasn't crazy enough in the first place...

...wish me luck :)

Sunday, April 22, 2012

Back to High-Res


Nice, but too much variance :(

k-d Visualization

Just as a sanity check, I decided to make sure that my k-d implementation is actually working.  I visualized the "work" that each pixel is doing (where work is the number of kd cell traversals).

Here's an image of the asteroid scene with this visualization:


Indeed, it works!  Not only that, but I was amazed by how precise the tree was.  If you look closely you can see the grid-like structures of the k-d splitting planes.  I had no idea that they could partition the scene so effectively!  No wonder I haven't been able to get any improvements by tweaking the construction (I'm using the surface area heuristic, so I should be getting almost-optimal trees).

Well, that's good...but it's getting really hard to figure out where I'm going to find that last 2-3x performance boost that I need.  I've tried several types of data compression (in particular, I cut down the scene size by half using fixed-point shorts, but that only lowered performance).  I've tried refactoring the shader in many different ways to no avail.  I've tried adding an index buffer to conserve vertex storage...which hurt performance.

I'm unsure of where I'm losing performance.  I thought I was bandwidth-limited, but attempts at compression seem to reveal otherwise.  Yet arithmetic optimization isn't yielding any fruit either.  Where are you hiding, you sneaky clock cycles?  Is this really as good as it's going to get without CUDA?  I hope not.

Saturday, April 21, 2012

RAWR.

I'm pretty angry right now.  Just when I was about to give up on texture buffers, I thought to myself, "you know what, GPU memory and OpenGL are both so stupid that I'll bet changing one of these random enums could totally change everything."

I mean, it makes a lot of sense to specify GL_STATIC_READ for a buffer that's going to be read and never changed...amiright???

So guess what happened when I changed it to GL_STATIC_COPY?  Performance +50%.  Yep.  Wait, what? I thought read-only memory was the fastest?  Shouldn't that memory get shipped over to the GPU and never have to look back?

Am I going insane or did the definition of "read" change drastically since the good-old D3D9 days?

Wow.  Well, there you have it.  All-in-all, I'm up about 75% in performance from yesterday.  Looking good, but I still need more.  But hey, given how random things like changing an enum can give you +50%, I guess there's reason to be hopeful, right?

(Sorry for the rant.)

GPU Memory Sucks

I don't understand why they would provide a specific construct just for allowing large arrays to be accessed from shaders (texture buffer objects), when said construct is slower than regular 2D textures for large arrays.  Lolwhat?!?

I just wasted 1.5 hours trying out texture buffers.  Well, it turns out they work well for tiny scenes (Cornell Box +25% performance), and terrible for large ones (real scenes -50% performance).

That was an annoying waste of time... :(

Slight Optimizations

I've managed to improve the acceleration speed a bit by moving bounding boxes to fixed-point format in the index texture (so that they're adjacent to the other information in their corresponding cells), as well as by making the traversal algorithm smarter and leaner.  Still, I haven't achieved that order-of-magnitude speedup that would seal the deal once and for all.  Seriously, if I could just get 5-10x faster, I would cast away PBRT forever.  But I can't just yet.  And I'm not sure where I'm going to find that kind of speedup, but, given how unpredictable GPU optimization seems to be, I'm hopeful that it's lurking somewhere, just waiting to be tapped.


That's a super-high-res ship (half a million polys), and it took about 15-20 minutes to render (~1200 SPP).  At least I now know that high geometric complexity is possible with this tracer (I strongly doubt that we would have seen that kind of performance from the uniform grid).

Better Participating Media

Still not perfect, but I'm able to get much thicker-looking media now, with proper scattering (not how the dense cloud reflects the top light's photons back onto the top of the box, where they can escape at the edges).

I definitely won't use anything this thick for the asteroid field, but it's cool to see.


Friday, April 20, 2012

Russian Roulette

Russian Roulette for path tracing is really a beautiful thing.  I didn't fully understand the point until now.  Here's the beauty: it completely solves the whole "ray depth" thing.  With RR, you can set your depth absurdly high with almost no performance hit (well, unless everything in your scene is *really* reflective).  Why? Because very few rays carry any significant amount of information after a few bounces, so there's really no point in tracing them.  Still, if you just discard all rays below a certain radiance or limit the bounce depth, you introduce bias.

With RR, you get as much bounce depth as you want, discard the unimportant rays probabilistically, and have no bias in the end but much faster results.


Oh, and I've finally made a simple, movable camera.  With some optimizations to the the tracer, I'm now able to actually move around the scene a bit.

More optimizations to come!

K-D Trees on the GPU!

I finally got k-d trees running in my path tracer.  The speedup isn't as great as I would have hoped (in fact, it's not much different than a uniform grid..), but I haven't optimized anything yet.



I'm hopeful that, with optimization, I'll see better results.  On the bright side, the kd tree takes less pre-processing time than the uniform grid, and is overall a much smarter structure that requires less tweaking.

Let's hope optimization pulls through...this tracer is *right* on the edge of being usable.

Thursday, April 19, 2012

Better Scattering

I devoted some time today to reading PBR and using the information therein to improve my understanding of volumetric scattering.  The result is that I now have much better-looking gas.  The scattering in this image is pretty much representative of what I'd like to see in the final image with the mining beam, although I'd also like the final gas to be non-homogeneous.


Not surprisingly, the gas increases the variance (although I didn't give the above image very long to render anyway).  The performance hit is not so bad compared to the hit incurred by large scenes. It's clear that my primary optimization target should be scene traversal/acceleration structures.  Tomorrow I will try to implement kD trees and the ropes++ traversal algorithm described here: https://www.gprt.ufpe.br/grvm/Publication/FullPapers/2009/SBACPAD2009_Santosetal.pdf

Oh, and if you take a median filter...I guess it looks kind of good :P


Wednesday, April 18, 2012

Not Bad

Not a bad little scene to end another long night of work.  I'm still pretty upset that my bounding box scheme didn't work, leaving me more confused than ever about the true bottleneck of the tracer...nonetheless, I'm content enough with the progress to call it a night.


100k

I'm obviously doing something wrong in my bounding box code, as right now it's actually hurting the render speed.  I would have thought that a coarse bounding box pass would yield immense gains :/

On the bright side, my path tracer has finally produced its first-ever >100k triangle image!  This is what I would call a mid-resolution ship.  It's not as high-quality as I want for the final scene, but it's not terrible either.  So perhaps my tracer isn't too far off the mark...



Still, it bothers me that this took 5 minutes and the depth was only set to 5...it's also pretty low-resolution.  I guess it's better than last night's image.  Oh, and those black boxes?  Yeah, there's obviously a problem with my acceleration grid.  I'll debug that later -_-

Tuesday, April 17, 2012

Slightly Better

Uniform grid acceleration in all 3 dimension now.  Better/faster raymarching, better grid storage management, even some rudimentary compression.

Still pretty underwhelming results, but at least I can get >10K tris on screen with this method.  That's way better than before.  I'm still nowhere near PBRT, and CPU + MLT is looking pretty good right now...but I just can't let go of the hope that, if I persevere with this GPU path tracer, I may get lucky in the end :)


Not Much Hope to Cling To...

I spent 2 days building an acceleration structure for the tracer.  The first one was trashed when I found out how absurdly slow GLSL constant memory is.  I'm now using texture fetches for everything.  I'm on my second iteration now, and things are slightly less-excruciatingly-bad, but it's clear that my run of awesome luck has ended.

Here's the bottom line: dependent texture fetches on the GPU are slow. REALLY SLOW.  I mean, we all knew that.  But seriously.  They're crazy slow.

Well, here's a thread of hope to cling to:



A hideous, low-res blob that looks nothing like a spaceship, and a decapitated Cornell Box (no, it's not a glitch, I removed the floor and ceiling).  Some hope, right?

Hey, it's a ship.  A path-traced ship.  That's a start?

Sunday, April 15, 2012

Wallpapers

Because I love this scene so much...



Smooth Normals

Yes sir, if you ever wanted to torture a GPU, right here's the best way.  Path tracing with no acceleration structures, using two 128-bit textures to store scene data, 100+ triangle intersection tests each step with barycentric normal interpolation, and, as if that wasn't bad enough, a heterogeneous participating medium.

Kudos to you, EVGA GTX 560, for surviving the bloodbath.


Yes indeed, that sphere in the middle is made out of triangles.  I'm not too sure what's going on at the edges...can't tell if those are just artifacts from it being a triangle mesh, or if there's actually a problem with normal interpolation.  For the most part, however, it looks good.

Triangle Mesh

First attempt ever to read dynamic scene data in the shader using textures...and it worked!  As expected, everything is terribly slow.  But, hey, it still converges in a reasonable amount of time, and I haven't even started with acceleration structures.



Yes, that thing in the middle is a pretty sad excuse for a sphere.  It will look better if I can implement vertex normal interpolation.

Better Dust

I worked for quite a while trying to get energy conservation working and looking good in the tracer.  The results are great, as the hazy scattering effect is much cleaner and more pronounced.


The gas in this scene is concentrated around the light, and is distributed with a density that varies according to the sine of the horizontal axis (hence the visible bands in the gas).  That's an intentional effect to test how the scattering looks in a non-homogeneous distribution of gas.  This look is just what I had hoped for!

Whoa

Here's what our world would look like if photons couldn't figure out how to bounce off things properly...


Kind of nice!

Saturday, April 14, 2012

Dust

I almost hate to post anything after that last image...unfortunately, we must move on!

I've started playing with dust/participating media.  Ultimately, the quality of the "haze" affect that I can achieve will be what determines whether or not my path tracer or PBRT would be the preferred solution for rendering my scene.

So far, the effect is nice, but not super-compelling.  I'm sure it's totally wrong, though, as it's only my first pass.


Still, you can definitely see the haze.  Since it's somewhat homogeneous, it's not a very interesting effect.  Hopefully I'll be able to spice that up later.

Widescreen

I loved that last shot so much that I had to redo it in widescreen.  Man, path tracing is beautiful!  This would have taken my old path tracer (CPU-based) about...maybe...12 hours or so?  It took the GPU about 3 minutes.

Good life lesson: as it turns out, constant factors DO matter.  A lot.


Cool

It's the same tracer...there's just something beautiful about glossy surfaces :) Oh yes, my ship will *definitely* need to be glossy!


There We Go!

Render time: ~30 seconds.  Looks like I'm getting pretty darn close to physical realism :)


Friday, April 13, 2012

Accumulation

Implemented accumulation, now the path tracer (like most other cool GPU tracers) updates in real-time, so that you can see the noise slowly disappearing.


This clearly still isn't physically accurate...I think the direct illumination model that I'm using as the final step is causing some pretty bad bias.

Still, not bad for a day's work.  And, on the bright side, it's really fast! The image above took about 15 seconds to accumulate!

Still Better...

Looks like most of the bugs are gone! :D


Better

That's a lot better...


Still having some bad times with the noise function, but that's to be expected.  Getting the noise right will just take a lot of tweakery.

GPU Path Tracing!

Ouch, yeah.  Well, come on.  It's only been a day.


Reflections


First GLSL Ray Tracer

Here's the plan.  PBRT is great, but it doesn't have good support for volumetric-type stuff in combination with Metropolis/path tracing.  I'm pretty sure I need path tracing to get good results in this scene.  I don't think I want to implement volumetric photon mapping in PBRT...especially since I have no idea how that would interact with MLT (I assume the interaction would be fairly complex...).

But the hardcore rendering part of this project is supposed to be about the interaction of light in a hazy asteroid field.

So here's the plan: I'm going to try to write a GPU path tracer to render the scene.  That one sentence is all you need to read to know that I'm absolutely doomed to failure.  Even still, I'm going to try my hardest.  I'm sure I'll run up against infinitely many GLSL limitations (no, I'm not even going to use CUDA...).  But I'm still going to try :)


To that end, I preset my first GLSL ray tracer! Nothing fancy, but it's a start.

Impressive

The image? No, that's not impressive.  What impresses me is that I was expecting PBRT to crash - or at least bring my computer to a grinding halt for several hours - when I threw in an ultra-high-quality-ship-with-lame-greeble (a 50MB model in PBRT format) and asked for a path-traced image.

And you know what? It gave me one...in about 5 minutes.  Wow.


I'm happy.  Does this mean that we can get away with pushing the procedural models to absurd levels of detail that nobody could produce by hand?  Yes, yes it does.  And that's where this project will shine :)

(Edit: here's a version with the exaggerated red lighting. I kind of like this as well.)


Thursday, April 12, 2012

At Least it's Reflective...

Same shot, two different styles of lighting (although I swapped out the asteroids in the latter to see if one looked less jagged than the other).



Conclusions:

  1. Path Tracing + Glossy Surface = Good. (we all knew this already, yes?)
  2. Normals on Voronoi-Displaced Sphere (aka asteroid) = Bad. Seriously, something will need to be done about this.
  3. Asteroids should not cast shadows on a background spanning billions of lightyears of stars and nebulae.  Well, I guess that cheap backdrop wasn't really fooling anyone in the first place...
Yeah, there's a lot of bad going on in these shots, but no one can say that I'm not making progress :)