Advertisement
Guest User

Sh-Coeff fn

a guest
Jan 25th, 2015
491
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.01 KB | None | 0 0
  1.     void sphericalHarmonicsEvaluateDirection(float * result, int order,
  2.         const Math::Vector3 & dir)
  3.     {
  4.         result[0] = 0.282095;
  5.         result[1] = 0.488603 *  dir.y;
  6.         result[2] = 0.488603 *  dir.z;
  7.         result[3] = 0.488603 *  dir.x;
  8.         result[4] = 1.092548 *  dir.x*dir.y;
  9.         result[5] = 1.092548 *  dir.y*dir.z;
  10.         result[6] = 0.315392 * (3.f*dir.z*dir.z - 1.f);
  11.         result[7] = 1.092548 *  dir.x * dir.z;
  12.         result[8] = 0.546274 * (dir.x*dir.x - dir.y*dir.y);
  13.     }
  14.  
  15.     void sphericalHarmonicsAdd(float * result, int order,
  16.         const float * inputA, const float * inputB)
  17.     {
  18.         const int numCoeff = order * order;
  19.         for (int i = 0; i < numCoeff; i++)
  20.         {
  21.             result[i] = inputA[i] + inputB[i];
  22.         }
  23.     }
  24.  
  25.     void sphericalHarmonicsScale(float * result, int order,
  26.         const float * input, float scale)
  27.     {
  28.         const int numCoeff = order * order;
  29.         for (int i = 0; i < numCoeff; i++)
  30.         {
  31.             result[i] = input[i] * scale;
  32.         }
  33.     }
  34.  
  35.  
  36.  
  37.     void sphericalHarmonicsFromTexture(GLuint cubeTexture,
  38.         std::vector<Math::Vector3> & output, const uint order)
  39.     {
  40.         const uint sqOrder = order*order;
  41.  
  42.         // allocate memory for calculations
  43.         output.resize(sqOrder);
  44.         std::vector<float> resultR(sqOrder);
  45.         std::vector<float> resultG(sqOrder);
  46.         std::vector<float> resultB(sqOrder);
  47.  
  48.         // variables that describe current face of cube texture
  49.         GLubyte* data;
  50.         GLint width, height;
  51.         GLint internalFormat;
  52.         GLint numComponents;
  53.  
  54.         // initialize values
  55.         float fWt = 0.0f;
  56.         for (uint i = 0; i < sqOrder; i++)
  57.         {
  58.             output[i].x = 0;
  59.             output[i].y = 0;
  60.             output[i].z = 0;
  61.             resultR[i] = 0;
  62.             resultG[i] = 0;
  63.             resultB[i] = 0;
  64.         }
  65.         std::vector<float> shBuff(sqOrder);
  66.         std::vector<float> shBuffB(sqOrder);
  67.        
  68.        
  69.         const GLenum cubeSides[6] = {
  70.             GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // Top
  71.             GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // Left
  72.             GL_TEXTURE_CUBE_MAP_POSITIVE_Z, // Front
  73.             GL_TEXTURE_CUBE_MAP_POSITIVE_X, // Right
  74.             GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, // Back
  75.             GL_TEXTURE_CUBE_MAP_NEGATIVE_Y // Bottom
  76.         };
  77.  
  78.         // bind current texture
  79.         glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTexture);
  80.  
  81.         int level = 0;
  82.         // for each face of cube texture
  83.         for (int face = 0; face < 6; face++)
  84.         {
  85.             // get width and height
  86.             glGetTexLevelParameteriv(cubeSides[face], level, GL_TEXTURE_WIDTH, &width);
  87.             glGetTexLevelParameteriv(cubeSides[face], level, GL_TEXTURE_HEIGHT, &height);
  88.  
  89.             if (width != height)
  90.             {
  91.                 return;
  92.             }
  93.  
  94.             // get format of data in texture
  95.  
  96.             glGetTexLevelParameteriv(cubeSides[face], level,
  97.                 GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
  98.  
  99.             // get data from texture
  100.             if (internalFormat == GL_RGBA)
  101.             {
  102.                 numComponents = 4;
  103.                 data = new GLubyte[numComponents * width * width];
  104.             }
  105.             else if (internalFormat == GL_RGB)
  106.             {
  107.                 numComponents = 3;
  108.                 data = new GLubyte[numComponents * width * width];
  109.             }
  110.             else
  111.             {
  112.                 return;
  113.             }
  114.             glGetTexImage(cubeSides[face], level, internalFormat, GL_UNSIGNED_BYTE, data);
  115.  
  116.             // step between two texels for range [0, 1]
  117.             float invWidth = 1.0f / float(width);
  118.             // initial negative bound for range [-1, 1]
  119.             float negativeBound = -1.0f + invWidth;
  120.             // step between two texels for range [-1, 1]
  121.             float invWidthBy2 = 2.0f / float(width);
  122.  
  123.             for (int y = 0; y < width; y++)
  124.             {
  125.                 // texture coordinate V in range [-1 to 1]
  126.                 const float fV = negativeBound + float(y) * invWidthBy2;
  127.  
  128.                 for (int x = 0; x < width; x++)
  129.                 {
  130.                     // texture coordinate U in range [-1 to 1]
  131.                     const float fU = negativeBound + float(x) * invWidthBy2;
  132.  
  133.                     // determine direction from center of cube texture to current texel
  134.                     Math::Vector3 dir;
  135.                     switch (cubeSides[face])
  136.                     {
  137.                     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
  138.                         dir.x = 1.0f;
  139.                         dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
  140.                         dir.z = 1.0f - (invWidthBy2 * float(x) + invWidth);
  141.                         //dir = -dir;
  142.                         break;
  143.                     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
  144.                         dir.x = -1.0f;
  145.                         dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
  146.                         dir.z = -1.0f + (invWidthBy2 * float(x) + invWidth);
  147.                         //dir = dir;
  148.                         break;
  149.                     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
  150.                         dir.x = -1.0f + (invWidthBy2 * float(x) + invWidth);
  151.                         dir.y = 1.0f;
  152.                         dir.z = -1.0f + (invWidthBy2 * float(y) + invWidth);
  153.                         //dir = dir;
  154.                         break;
  155.                     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
  156.                         dir.x = -1.0f + (invWidthBy2 * float(x) + invWidth);
  157.                         dir.y = -1.0f;
  158.                         dir.z = 1.0f - (invWidthBy2 * float(y) + invWidth);
  159.                         //dir = dir; //!
  160.                         break;
  161.                     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
  162.                         dir.x = -1.0f + (invWidthBy2 * float(x) + invWidth);
  163.                         dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
  164.                         dir.z = 1.0f;
  165.                         break;
  166.                     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
  167.                         dir.x = 1.0f - (invWidthBy2 * float(x) + invWidth);
  168.                         dir.y = 1.0f - (invWidthBy2 * float(y) + invWidth);
  169.                         dir.z = -1.0f;
  170.                         break;
  171.                     default:
  172.                         return;
  173.                     }
  174.  
  175.                     // normalize direction
  176.                     dir = Math::Normalize(dir);
  177.  
  178.  
  179.                     // scale factor depending on distance from center of the face
  180.                     const float fDiffSolid = 4.0f / ((1.0f + fU*fU + fV*fV) *
  181.                         sqrtf(1.0f + fU*fU + fV*fV));
  182.                     fWt += fDiffSolid;
  183.  
  184.                     // calculate coefficients of spherical harmonics for current direction
  185.                     sphericalHarmonicsEvaluateDirection(shBuff.data(), order, dir);
  186.  
  187.                     // index of texel in texture
  188.                     uint pixOffsetIndex = (x + y * width) * numComponents;
  189.                     // get color from texture and map to range [0, 1]
  190.                     Math::Vector3 clr(
  191.                         float(data[pixOffsetIndex]) / 255,
  192.                         float(data[pixOffsetIndex + 1]) / 255,
  193.                         float(data[pixOffsetIndex + 2]) / 255
  194.                         );
  195.  
  196.                     //clr.x = pow(clr.x, 1.1f);
  197.                     //clr.y = pow(clr.y, 1.1f);
  198.                     //clr.z = pow(clr.z, 1.1f);
  199.  
  200.                     clr.x = clr.x*0.5f;
  201.                     clr.y = clr.y*0.5f;
  202.                     clr.z = clr.z*0.5f;
  203.  
  204.                     // scale color and add to previously accumulated coefficients
  205.                     sphericalHarmonicsScale(shBuffB.data(), order,
  206.                         shBuff.data(), clr.x * fDiffSolid);
  207.                     sphericalHarmonicsAdd(resultR.data(), order,
  208.                         resultR.data(), shBuffB.data());
  209.  
  210.                     sphericalHarmonicsScale(shBuffB.data(), order,
  211.                         shBuff.data(), clr.y * fDiffSolid);
  212.                     sphericalHarmonicsAdd(resultG.data(), order,
  213.                         resultG.data(), shBuffB.data());
  214.  
  215.                     sphericalHarmonicsScale(shBuffB.data(), order,
  216.                         shBuff.data(), clr.z * fDiffSolid);
  217.                     sphericalHarmonicsAdd(resultB.data(), order,
  218.                         resultB.data(), shBuffB.data());
  219.                 }
  220.             }
  221.  
  222.             delete[] data;
  223.         }
  224.  
  225.         // final scale for coefficients
  226.         const float fNormProj = (4.0f * Math::PI<float>()) / fWt;
  227.         sphericalHarmonicsScale(resultR.data(), order, resultR.data(), fNormProj);
  228.         sphericalHarmonicsScale(resultG.data(), order, resultG.data(), fNormProj);
  229.         sphericalHarmonicsScale(resultB.data(), order, resultB.data(), fNormProj);
  230.  
  231.         // save result
  232.         for (uint i = 0; i < sqOrder; i++)
  233.         {
  234.             output[i].x = resultR[i];
  235.             output[i].y = resultG[i];
  236.             output[i].z = resultB[i];
  237.         }
  238.  
  239.         //glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  240.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement