How to do it...

To modify the shadow mapping algorithm and to use this random sampling technique, perform the following steps. We'll build the offset texture within the main OpenGL program, and make use of it within the fragment shader:

  1. Use the following code within the main OpenGL program to create the offset texture. This only needs to be executed once during the program's initialization:
void buildOffsetTex(int size, int samplesU, int samplesV) {
  int samples = samplesU * samplesV; 
  int bufSize = size * size * samples * 2; 
  float *data = new float[bufSize]; 
 
  for( int i = 0; i< size; i++ ) { 
    for(int j = 0; j < size; j++ ) { 
      for( int k = 0; k < samples; k += 2 ) { 
        int x1,y1,x2,y2; 
        x1 = k % (samplesU); 
        y1 = (samples - 1 - k) / samplesU; 
        x2 = (k+1) % samplesU; 
        y2 = (samples - 1 - k - 1) / samplesU; 
 
        glm::vec4 v; 
        // Center on grid and jitter 
        v.x = (x1 + 0.5f) + jitter(); 
        v.y = (y1 + 0.5f) + jitter(); 
        v.z = (x2 + 0.5f) + jitter(); 
        v.w = (y2 + 0.5f) + jitter(); 
        // Scale between 0 and 1 
        v.x /= samplesU; 
        v.y /= samplesV; 
        v.z /= samplesU; 
        v.w /= samplesV; 
        // Warp to disk 
        int cell = ((k/2) * size * size + j *  
                    size + i) * 4; 
        data[cell+0] = glm::sqrt(v.y) * glm::cos(glm::two_pi<float>
()*v.x); data[cell+1] = glm::sqrt(v.y) * glm::sin(glm::two_pi<float>
()*v.x); data[cell+2] = glm::sqrt(v.w) * glm::cos(glm::two_pi<float>
()*v.z); data[cell+3] = glm::sqrt(v.w) * glm::sin(glm::two_pi<float>
()*v.z); } } } glActiveTexture(GL_TEXTURE1); GLuint texID; glGenTextures(1, &texID); glBindTexture(GL_TEXTURE_3D, texID); glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA32F, size, size, samples/2); glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, size, size, samples/2, GL_RGBA, GL_FLOAT, data); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); delete [] data; } // Return random float between -0.5 and 0.5 float jitter() {
static std::default_random_engine generator;
static std::uniform_real_distribution<float> distrib(-0.5f, 0.5f);
return distrib(generator);
}
  1. Add the following uniform variables to the fragment shader:
uniform sampler3D OffsetTex; 
uniform vec3 OffsetTexSize; // (width, height, depth) 
uniform float Radius;
  1. Use the following code for the shadeWithShadow function in the fragment shader:
subroutine (RenderPassType) 
void shadeWithShadow() {
  vec3 ambient = vec3(0.2); 
  vec3 diffSpec = diffAndSpec(); 
 
  ivec3 offsetCoord; 
  offsetCoord.xy = ivec2( mod( gl_FragCoord.xy,  
                         OffsetTexSize.xy ) ); 
 
  float sum = 0.0; 
  int samplesDiv2 = int(OffsetTexSize.z); 
  vec4 sc = ShadowCoord; 
 
  for( int i = 0 ; i< 4; i++ ) { 
    offsetCoord.z = i; 
    vec4 offsets = texelFetch(OffsetTex,offsetCoord,0) *  
                       Radius * ShadowCoord.w; 
 
    sc.xy = ShadowCoord.xy + offsets.xy; 
    sum += textureProj(ShadowMap, sc); 
    sc.xy = ShadowCoord.xy + offsets.zw; 
    sum += textureProj(ShadowMap, sc); 
  } 
  float shadow = sum / 8.0; 
 
  if( shadow != 1.0 && shadow != 0.0 ) { 
    for( int i = 4; i< samplesDiv2; i++ ) { 
      offsetCoord.z = i; 
      vec4 offsets =  
        texelFetch(OffsetTex, offsetCoord,0) * 
                   Radius * ShadowCoord.w; 
 
      sc.xy = ShadowCoord.xy + offsets.xy; 
      sum += textureProj(ShadowMap, sc); 
      sc.xy = ShadowCoord.xy + offsets.zw; 
      sum += textureProj(ShadowMap, sc); 
    } 
    shadow = sum / float(samplesDiv2 * 2.0); 
  } 
  FragColor = vec4(diffSpec * shadow + ambient, 1.0); 
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.23.127.197