<commit_before>#+TITLE: Hadoom Developer Log

* <2014-12-15 Mon>

Spent most of the day continuing work on attempting to implement the ideas in
the paper "exponential soft shadow mapping", though didn't reach the desired
solution. Spent a lot of time trying to successfully render into an integer
texture. The following checklist should help me avoid these problems in the
future:

1. Create the texture with =GL_RG32UI= (or another appropriate integer texture).
2. Make sure to output using the correct type. Note that vectors have their own
   types too! =vec2= is a vector of /floats/ - the aforementioned texture should
   be used with a =uvec2=.
3. Make sure to use the correct type of sampler. There are samplers for each
   type - =GL_RG32UI= should be sampled with =usampler2D=.
4. Make sure to sample with the generic =texture()= function.

To store floating point values in an integer texture, we can either

1. Use =floatBitsToInt= -- essentially a "reinterpreting" cast.
2. Scale the float (assumed to be in the range [0, 1]) by 2^n, where =n= is the
   amount of bits of precision required.

WARNING! The expression =2^n= in GLSL does *not* mean what you might think it
means. =^= is the operator for bitwise XOR. We should use =exp2= to raise 2 to
an arbitrary power. However, there was *another* problem - scaling by =exp2(16)=
seemed to be ok, but scaling by =exp2(17)= was not. It seems that we have to use
a =double= rather than a =float=, or Strange Things happen. I should revisit
this at some point to form a better understanding of what's going wrong.

Past that hurdle, I was able to successfully store various depths in my integer
depth texture. I believe, from reading the paper, that I should be storing
=exp(cz)= in the texture, but I am only storing my (linear) =z= value:

    fragmentdepth = ivec4(uint(round(esmNormalized * scale)));

It's unclear to me how you store =exp(cz)= in the integer texture and later
actually do something with it, as you have to scale it to [0, 1]. The scaling
could be reversed, but I think I'm missing something here.

I didn't get to make a start with their idea of "tiled" summed area tables, as I
spent most of the time trying to work out how the blocker depth estimate
works. I found another people with a better discussion of this - "Real-Time,
All-Frequency Shadows in Dynamic Scenes". This paper lead me on to reading about
"Convolution Shadow Maps", but importantly has a good discussion on estimating
the blocker depth.

* <2014-12-16 Tue>

Started the day by wanting to look at computing the average blocker
distance. Reading the "Real-Time, All-Frequency Shadows" paper again last night
has made the computation clearer - you essentially perform the binary shadow
test function and multiple the result against the depth of the point you are
testing. If you average all of these, you get the average depth of blockers at a
point. The use of the shadow function multiplied by the depth means we can use
our same approximation to the shadow function, which means we can move the
convolution to pre-filtering, provided we multiply the bias (exp(cz)) by the
depth (so we store exp(cz)z).

However, this means that my depth shader should be outputting exp(cz) and
scaling it, which it doesn't currently do. I started by looking into that, but I
haven't managed to get anything satisfactory yet.

Another oddity came up during debugging - if I shade only the depth as seen by
the light, for some reason the column appears *below* the column as scene by the
camera. This doesn't seem correct to me, as my understanding is that we are
projecting the depth the camera sees onto the scene, so the column depth should
be projected directly onto the column, and not the floor below it. I'd like to
verify if this is a bug or correct before moving on.

** <2014-12-16 Tue 11:07>

I solved the last problem mentioned above. While I thought that the projection
was wrong, it turns out there isn't a problem there at all. The problem was this
one missing line from when I set up the light's framebuffer object:

     glFramebufferRenderbuffer GL_FRAMEBUFFER GL_DEPTH_ATTACHMENT GL_RENDERBUFFER rbo

That's right - I built the framebuffer object that will be used to render the
light, but I forgot to attach the render bufffer that will be used to store
depth information! Thus the weird projection was actually due to a badly drawn
depth buffer, as I wasn't making use of a depth buffer while rendering it. Oops.

* <2014-12-16 Tue 15:23>

I decided to just crack on with getting a variable penumbra width without doing
any prefiltering at all, just to get an understanding of what it is I'm actually
trying to do. Using brute force box filters, I finally have the results I'm
looking for! I begin by finding the average blocker depth - sampling a fixed
size kernel around the sample point to find the depth of other points that would
cast shadows. Once I know the average depth of blockers around this point, I can
use this to determine the size of the box filter to use during percentage closer
filtering.

Currently I've got this working with fairly small area lights and I am getting
the results I'd expect. As the size of the area light increases, naturally the
framerate drops rapidly - but this is to be expected as we're using O(n^2)
filters.

In the next few days, I should have an understanding of how to store the
exponential data in my shadow map, at which point I can start looking at
building a summed area table and getting back to constant time blurs.<commit_msg>Dev log update<commit_after>#+TITLE: Hadoom Developer Log

* <2014-12-15 Mon>

Spent most of the day continuing work on attempting to implement the ideas in
the paper "exponential soft shadow mapping", though didn't reach the desired
solution. Spent a lot of time trying to successfully render into an integer
texture. The following checklist should help me avoid these problems in the
future:

1. Create the texture with =GL_RG32UI= (or another appropriate integer texture).
2. Make sure to output using the correct type. Note that vectors have their own
   types too! =vec2= is a vector of /floats/ - the aforementioned texture should
   be used with a =uvec2=.
3. Make sure to use the correct type of sampler. There are samplers for each
   type - =GL_RG32UI= should be sampled with =usampler2D=.
4. Make sure to sample with the generic =texture()= function.

To store floating point values in an integer texture, we can either

1. Use =floatBitsToInt= -- essentially a "reinterpreting" cast.
2. Scale the float (assumed to be in the range [0, 1]) by 2^n, where =n= is the
   amount of bits of precision required.

WARNING! The expression =2^n= in GLSL does *not* mean what you might think it
means. =^= is the operator for bitwise XOR. We should use =exp2= to raise 2 to
an arbitrary power. However, there was *another* problem - scaling by =exp2(16)=
seemed to be ok, but scaling by =exp2(17)= was not. It seems that we have to use
a =double= rather than a =float=, or Strange Things happen. I should revisit
this at some point to form a better understanding of what's going wrong.

Past that hurdle, I was able to successfully store various depths in my integer
depth texture. I believe, from reading the paper, that I should be storing
=exp(cz)= in the texture, but I am only storing my (linear) =z= value:

    fragmentdepth = ivec4(uint(round(esmNormalized * scale)));

It's unclear to me how you store =exp(cz)= in the integer texture and later
actually do something with it, as you have to scale it to [0, 1]. The scaling
could be reversed, but I think I'm missing something here.

I didn't get to make a start with their idea of "tiled" summed area tables, as I
spent most of the time trying to work out how the blocker depth estimate
works. I found another people with a better discussion of this - "Real-Time,
All-Frequency Shadows in Dynamic Scenes". This paper lead me on to reading about
"Convolution Shadow Maps", but importantly has a good discussion on estimating
the blocker depth.


* <2014-12-16 Tue>

Started the day by wanting to look at computing the average blocker
distance. Reading the "Real-Time, All-Frequency Shadows" paper again last night
has made the computation clearer - you essentially perform the binary shadow
test function and multiple the result against the depth of the point you are
testing. If you average all of these, you get the average depth of blockers at a
point. The use of the shadow function multiplied by the depth means we can use
our same approximation to the shadow function, which means we can move the
convolution to pre-filtering, provided we multiply the bias (exp(cz)) by the
depth (so we store exp(cz)z).

However, this means that my depth shader should be outputting exp(cz) and
scaling it, which it doesn't currently do. I started by looking into that, but I
haven't managed to get anything satisfactory yet.

Another oddity came up during debugging - if I shade only the depth as seen by
the light, for some reason the column appears *below* the column as scene by the
camera. This doesn't seem correct to me, as my understanding is that we are
projecting the depth the camera sees onto the scene, so the column depth should
be projected directly onto the column, and not the floor below it. I'd like to
verify if this is a bug or correct before moving on.

** <2014-12-16 Tue 11:07>

I solved the last problem mentioned above. While I thought that the projection
was wrong, it turns out there isn't a problem there at all. The problem was this
one missing line from when I set up the light's framebuffer object:

     glFramebufferRenderbuffer GL_FRAMEBUFFER GL_DEPTH_ATTACHMENT GL_RENDERBUFFER rbo

That's right - I built the framebuffer object that will be used to render the
light, but I forgot to attach the render bufffer that will be used to store
depth information! Thus the weird projection was actually due to a badly drawn
depth buffer, as I wasn't making use of a depth buffer while rendering it. Oops.


* <2014-12-16 Tue 15:23>

I decided to just crack on with getting a variable penumbra width without doing
any prefiltering at all, just to get an understanding of what it is I'm actually
trying to do. Using brute force box filters, I finally have the results I'm
looking for! I begin by finding the average blocker depth - sampling a fixed
size kernel around the sample point to find the depth of other points that would
cast shadows. Once I know the average depth of blockers around this point, I can
use this to determine the size of the box filter to use during percentage closer
filtering.

Currently I've got this working with fairly small area lights and I am getting
the results I'd expect. As the size of the area light increases, naturally the
framerate drops rapidly - but this is to be expected as we're using O(n^2)
filters.

In the next few days, I should have an understanding of how to store the
exponential data in my shadow map, at which point I can start looking at
building a summed area table and getting back to constant time blurs.


* <2014-12-18 Thu>

I've got to a point where I can reliably get results from the "percentage-closer
soft shadows" work. I found the original shader online [1], which has let me
understand more about the parameters in the implementation. I found out I was
many orders of magnitude out on my parameters, which explains why I was
struggling to reconcile my results with the paper. I am convinced the code has a
bug though. Where they estimate the blocker depth search filter size with

  lightSize / receiverDepth

I am certain that the *correct* formula would be

  lightSize * receiverDepth

By my reasoning, the potential area of blockers around a point is directly
proportional to its distance from the light. As we move away from the (area)
light source, the frustum formed by the point we are shading and the area light
intersects with less of the fixed shadow map plane. Taking the limit of distance
from the light, eventually the area light will be coincident with the shadow map
plane, thus we would desire a search size of 1 - the entire plane. After coming
back to this formula over and over again, I'm convinced it's the right one to
use - and it seems to give pleasing results.

I've understood more about what it means to filter shadow test
results. Performing a bilinear filter on the shadow map tests has to be done
after the shadow map test - so we sample 4 texels around our point, perform
shadow map tests on each of them and *then* bilinearly interpolate. This smooths
the edges, but with a big PCF kernel there is still very clear banding. I
shouldn't spend any more time on this though, because having a non-linear
spatial blur is never the goal anyway.

Next I want to move all of the shadow tests to use the exponential shadow
mapping approximation. Then I'll factor out the shadow map test from the
convolution (as per "Convolution Shadow Mapping"). At this point, I might be
able to start moving some of the calculation back to the light shader.

One other niceity - I finally implemented the ability to refresh shaders while
Hadoom is running. This makes a *huge* difference to my productivity. I might
even go all the way to using inotify to automatically refresh the shaders.

[1]: http://www.gamedev.net/topic/486151-soft-shadow-pcss/
{'fraction_non_alphanumeric': 0.04409118176364727, 'fraction_numerical': 0.011697660467906419, 'mean_word_length': 4.181429681429681, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1135737', 'n_tokens_mistral': 3604, 'n_tokens_neox': 3353, 'n_words': 2247}