title: Hardware PCF for Shadow Map using OpenGL
body: <p>I'm using OpenGL 4.3 under GeForce GTX 750 to create Shadow Map. Right now the basic effect, shown as below, seems to be correct:
  <a href="https://i.stack.imgur.com/4BbkW.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/4BbkW.png" alt="enter image description here"></a>
  To erase the blocky-effect, I've tried to do a 2x2 PCF manually in the shader. It leads to the following result, which also seems to be correct:
  <a href="https://i.stack.imgur.com/P61h6.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/P61h6.png" alt="enter image description here"></a>
  For acceleration, I want to use the benefit provided by the graphics card, which gives the linear filter of the comparison result with one fetch. But the effect was different from the above one. <strong>It is more like OpenGL filters the rendering of the shadow linearly, but not filters on the Shadow Map</strong>:
  <a href="https://i.stack.imgur.com/nPL0r.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/nPL0r.png" alt="enter image description here"></a>
  Below it's how I do the hardware PCF:
  I have noticed that the basic two things that have to be done in order to use the hardware PCF, which are:</p>
  
  <ol>
  <li>Using a <code>shadow</code> type sampler, which in my case, is <code>samplerCubeShadow</code> (I'm using a cube map type since I'm trying to create a point light scene).</li>
  <li><p>Set the comparison mode and filtering type, which in my case, is done by the following code:</p>
  
  <pre><code>glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
  </code></pre></li>
  </ol>
  
  <p>After that, I use the <code>texture</code> function in the shader like this (the reason that I use <code>texture</code> but not <code>textureProj</code> is because the latter doesn't seem to support cube map shadow texture since it will need a <code>vec5</code> type which is obviously not supported yet):</p>
  
  <pre><code>vec4 posInLight4D = positionsInLight / positionsInLight.w;    // divided by the 4-th component)
  vec3 texCoord = GetCubeMapTexCoord(posInLight4D.xy);    // get the texture coordinate in cube map texture. This can be assumed correct
  float lightness = texture(shadowMapHardware, vec4(texCoord, posInLight4D.z));
  </code></pre>
  
  <p>But unfortunately, this gives the result shown in the third picture. </p>
  
  <p>As far as I understand it, with the setting of the <strong>comparison mode</strong> and <strong>linear filter</strong>, the graphics card will <strong>do the comparison</strong> within a nearby 2x2 region and <strong>linearly interpolate the results</strong> and gives it back through the <code>texture</code> function. I think I've done all the necessary parts, but I still cannot get the exact result shown in the 2nd picture. </p>
  
  <p>Can anyone give me any suggestion about where I might go wrong? Thanks very much.</p>
  
  <p>ps: The interesting thing is: I tried the <code>textureGather</code> function, which only returns the comparison results but not does the filtering, and it gives the <strong>exact result as shown in the 2nd picture</strong>. But this lacks an automatic-filtering procedure and obviously it is not the complete version of hardware PCF.</p>