GLSL shader to handle multiple projections onto the same surface

For my project <a href="http://www.jotschi.de/?page_id=320">Generating City Models By Using Panorama Images</a> i have to write a fragment shader that handles multiple projections onto the same surface. The shader must contain condition in which the projection should be handled. In my case i had to decide which projection source should be used to texture the desired model. <a id="more"></a><a id="more-363"></a> I didn’t want to do alpha blending of each texture. I wanted that only the projection source will be used that would produce the best projection image. For a good projection the angle of which the projection 'light' falls onto the surface must be very low. The second parameter is the distance.

For example, imagine a scene with 20 projection sources. One source is very near the target surface but the angle in which the 'light' falls onto the surface is very big so the texture produced by such a source wouldn’t be that good. Instead there is another projection source which’s projections angle is very low but the distance is larger than that of the near source. My shader will now pick the second projection source because the first does not match its condtions.

Draft of my target shader:

uniform int nTextures;
uniform sampler2DArray textures;
uniform vec3[] projectPos;
varying vec3 glPos;
varying vec3 normalVec;
void main() {
  int currentTexture=0;
  float minAngle = 360.0f;
  float angleThreshold = 10.0f;
 // Select the texture with the lowest angle
  for(int i =0; i <nTextures; i++){
   float alpha = texture2DArray(textures,vec3(gl_TexCoord[0].xy, i)).a;
   if(alpha != 1.0f) {
     //TODO check calculation of projDirection
      vec3 projDirection =(projectPos-glPos);
      float angle = dot(normalVec,projDirection*-1);
      if(angle<minAngle) {
          minAngle = angle;
      }
    }
  }
  float minDistance= -1.0f;
  // Select the texture with the lowest distance among those around the lowest angle
  for(i=0; i <nTextures; i++){
   float alpha = texture2DArray(textures,vec3(gl_TexCoord[0].xy, i)).a;
   // Condition 1: Must be visible
   if (alpha != 1.0f) {
     //TODO check calculation of projDirection
     vec3 projDirection =( projectPos-glPos);
     float angle = dot(normalVec,projDirection);
     // Condition 2: The angle must be between +-10.0f of the lowest angle
     if(angle<(minAngle+angleThreshold) || angle>(minAngle+angleThreshold)) {
     // TODO check calculation of distance between both points within R³
    float dx = projectPos[i].x - glPos.x;
  float dy = projectPos[i].y - glPos.y;
  float dz = projectPos[i].z - glPos.z;
  float d = Math.sqrt(dx * dx + dy * dy + dz * dz);
    // select the texture with the lowest distance
    if(d<minDistance || minDistance  ==-1.0f)  {
          minDistance = d;
          currentTexture = i;
    }
        }
   }
  }
gl_FragColor = texture2DArray(textures,vec3(gl_TexCoord[0].xy, currentTexture));
}
  1. Maybe there is a better way to check if the given sample contains a texture value at the given texture coordinate than checking its alpha value.

  2. I use a uniform to handle the size of the sampler2DArray textures array. Maybe you can extract that information within the shader

  3. I use uniform vec3[] projectPos; to handle over the positions of the projection sources. Maybe this can be stored in the build in gl_LightSource array?