⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 texcompress_fxt1.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
   GLint i, k, best = 0;
   GLint sx, sx2;
   GLdouble var, maxvar = -1; /* small enough */
   GLdouble teenth = 1.0 / n;

   for (i = 0; i < nc; i++) {
      sx = sx2 = 0;
      for (k = 0; k < n; k++) {
         GLint t = input[k][i];
         sx += t;
         sx2 += t * t;
      }
      var = sx2 * teenth - sx * sx * teenth * teenth;
      if (maxvar < var) {
         maxvar = var;
         best = i;
      }
      if (variance) {
         variance[i] = var;
      }
   }

   return best;
}


static GLint
fxt1_choose (GLfloat vec[][MAX_COMP], GLint nv,
             GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
{
#if 0
   /* Choose colors from a grid.
    */
   GLint i, j;

   for (j = 0; j < nv; j++) {
      GLint m = j * (n - 1) / (nv - 1);
      for (i = 0; i < nc; i++) {
         vec[j][i] = input[m][i];
      }
   }
#else
   /* Our solution here is to find the darkest and brightest colors in
    * the 8x4 tile and use those as the two representative colors.
    * There are probably better algorithms to use (histogram-based).
    */
   GLint i, j, k;
   GLint minSum = 2000; /* big enough */
   GLint maxSum = -1; /* small enough */
   GLint minCol = 0; /* phoudoin: silent compiler! */
   GLint maxCol = 0; /* phoudoin: silent compiler! */

   struct {
      GLint flag;
      GLint key;
      GLint freq;
      GLint idx;
   } hist[N_TEXELS];
   GLint lenh = 0;

   memset(hist, 0, sizeof(hist));

   for (k = 0; k < n; k++) {
      GLint l;
      GLint key = 0;
      GLint sum = 0;
      for (i = 0; i < nc; i++) {
         key <<= 8;
         key |= input[k][i];
         sum += input[k][i];
      }
      for (l = 0; l < n; l++) {
         if (!hist[l].flag) {
            /* alloc new slot */
            hist[l].flag = !0;
            hist[l].key = key;
            hist[l].freq = 1;
            hist[l].idx = k;
            lenh = l + 1;
            break;
         } else if (hist[l].key == key) {
            hist[l].freq++;
            break;
         }
      }
      if (minSum > sum) {
         minSum = sum;
         minCol = k;
      }
      if (maxSum < sum) {
         maxSum = sum;
         maxCol = k;
      }
   }

   if (lenh <= nv) {
      for (j = 0; j < lenh; j++) {
         for (i = 0; i < nc; i++) {
            vec[j][i] = (GLfloat)input[hist[j].idx][i];
         }
      }
      for (; j < nv; j++) {
         for (i = 0; i < nc; i++) {
            vec[j][i] = vec[0][i];
         }
      }
      return 0;
   }

   for (j = 0; j < nv; j++) {
      for (i = 0; i < nc; i++) {
         vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (GLfloat)(nv - 1);
      }
   }
#endif

   return !0;
}


static GLint
fxt1_lloyd (GLfloat vec[][MAX_COMP], GLint nv,
            GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
{
   /* Use the generalized lloyd's algorithm for VQ:
    *     find 4 color vectors.
    *
    *     for each sample color
    *         sort to nearest vector.
    *
    *     replace each vector with the centroid of it's matching colors.
    *
    *     repeat until RMS doesn't improve.
    *
    *     if a color vector has no samples, or becomes the same as another
    *     vector, replace it with the color which is farthest from a sample.
    *
    * vec[][MAX_COMP]           initial vectors and resulting colors
    * nv                        number of resulting colors required
    * input[N_TEXELS][MAX_COMP] input texels
    * nc                        number of components in input / vec
    * n                         number of input samples
    */

   GLint sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */
   GLint cnt[MAX_VECT]; /* how many times a certain vector was chosen */
   GLfloat error, lasterror = 1e9;

   GLint i, j, k, rep;

   /* the quantizer */
   for (rep = 0; rep < LL_N_REP; rep++) {
      /* reset sums & counters */
      for (j = 0; j < nv; j++) {
         for (i = 0; i < nc; i++) {
            sum[j][i] = 0;
         }
         cnt[j] = 0;
      }
      error = 0;

      /* scan whole block */
      for (k = 0; k < n; k++) {
#if 1
         GLint best = -1;
         GLfloat err = 1e9; /* big enough */
         /* determine best vector */
         for (j = 0; j < nv; j++) {
            GLfloat e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) +
                      (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) +
                      (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]);
            if (nc == 4) {
               e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]);
            }
            if (e < err) {
               err = e;
               best = j;
            }
         }
#else
         GLint best = fxt1_bestcol(vec, nv, input[k], nc, &err);
#endif
         /* add in closest color */
         for (i = 0; i < nc; i++) {
            sum[best][i] += input[k][i];
         }
         /* mark this vector as used */
         cnt[best]++;
         /* accumulate error */
         error += err;
      }

      /* check RMS */
      if ((error < LL_RMS_E) ||
          ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) {
         return !0; /* good match */
      }
      lasterror = error;

      /* move each vector to the barycenter of its closest colors */
      for (j = 0; j < nv; j++) {
         if (cnt[j]) {
            GLfloat div = 1.0F / cnt[j];
            for (i = 0; i < nc; i++) {
               vec[j][i] = div * sum[j][i];
            }
         } else {
            /* this vec has no samples or is identical with a previous vec */
            GLint worst = fxt1_worst(vec[j], input, nc, n);
            for (i = 0; i < nc; i++) {
               vec[j][i] = input[worst][i];
            }
         }
      }
   }

   return 0; /* could not converge fast enough */
}


static void
fxt1_quantize_CHROMA (GLuint *cc,
                      GLubyte input[N_TEXELS][MAX_COMP])
{
   const GLint n_vect = 4; /* 4 base vectors to find */
   const GLint n_comp = 3; /* 3 components: R, G, B */
   GLfloat vec[MAX_VECT][MAX_COMP];
   GLint i, j, k;
   Fx64 hi; /* high quadword */
   GLuint lohi, lolo; /* low quadword: hi dword, lo dword */

   if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) {
      fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS);
   }

   FX64_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */
   for (j = n_vect - 1; j >= 0; j--) {
      for (i = 0; i < n_comp; i++) {
         /* add in colors */
         FX64_SHL(hi, 5);
         FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
      }
   }
   ((Fx64 *)cc)[1] = hi;

   lohi = lolo = 0;
   /* right microtile */
   for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) {
      lohi <<= 2;
      lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
   }
   /* left microtile */
   for (; k >= 0; k--) {
      lolo <<= 2;
      lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
   }
   cc[1] = lohi;
   cc[0] = lolo;
}


static void
fxt1_quantize_ALPHA0 (GLuint *cc,
                      GLubyte input[N_TEXELS][MAX_COMP],
                      GLubyte reord[N_TEXELS][MAX_COMP], GLint n)
{
   const GLint n_vect = 3; /* 3 base vectors to find */
   const GLint n_comp = 4; /* 4 components: R, G, B, A */
   GLfloat vec[MAX_VECT][MAX_COMP];
   GLint i, j, k;
   Fx64 hi; /* high quadword */
   GLuint lohi, lolo; /* low quadword: hi dword, lo dword */

   /* the last vector indicates zero */
   for (i = 0; i < n_comp; i++) {
      vec[n_vect][i] = 0;
   }

   /* the first n texels in reord are guaranteed to be non-zero */
   if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) {
      fxt1_lloyd(vec, n_vect, reord, n_comp, n);
   }

   FX64_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */
   for (j = n_vect - 1; j >= 0; j--) {
      /* add in alphas */
      FX64_SHL(hi, 5);
      FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F));
   }
   for (j = n_vect - 1; j >= 0; j--) {
      for (i = 0; i < n_comp - 1; i++) {
         /* add in colors */
         FX64_SHL(hi, 5);
         FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
      }
   }
   ((Fx64 *)cc)[1] = hi;

   lohi = lolo = 0;
   /* right microtile */
   for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) {
      lohi <<= 2;
      lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
   }
   /* left microtile */
   for (; k >= 0; k--) {
      lolo <<= 2;
      lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
   }
   cc[1] = lohi;
   cc[0] = lolo;
}


static void
fxt1_quantize_ALPHA1 (GLuint *cc,
                      GLubyte input[N_TEXELS][MAX_COMP])
{
   const GLint n_vect = 3; /* highest vector number in each microtile */
   const GLint n_comp = 4; /* 4 components: R, G, B, A */
   GLfloat vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */
   GLfloat b, iv[MAX_COMP]; /* interpolation vector */
   GLint i, j, k;
   Fx64 hi; /* high quadword */
   GLuint lohi, lolo; /* low quadword: hi dword, lo dword */

   GLint minSum;
   GLint maxSum;
   GLint minColL = 0, maxColL = 0;
   GLint minColR = 0, maxColR = 0;
   GLint sumL = 0, sumR = 0;

   /* Our solution here is to find the darkest and brightest colors in
    * the 4x4 tile and use those as the two representative colors.
    * There are probably better algorithms to use (histogram-based).
    */
   minSum = 2000; /* big enough */
   maxSum = -1; /* small enough */
   for (k = 0; k < N_TEXELS / 2; k++) {
      GLint sum = 0;
      for (i = 0; i < n_comp; i++) {
         sum += input[k][i];
      }
      if (minSum > sum) {
         minSum = sum;
         minColL = k;
      }
      if (maxSum < sum) {
         maxSum = sum;
         maxColL = k;
      }
      sumL += sum;
   }
   minSum = 2000; /* big enough */
   maxSum = -1; /* small enough */
   for (; k < N_TEXELS; k++) {
      GLint sum = 0;
      for (i = 0; i < n_comp; i++) {
         sum += input[k][i];
      }
      if (minSum > sum) {
         minSum = sum;
         minColR = k;
      }
      if (maxSum < sum) {
         maxSum = sum;
         maxColR = k;
      }
      sumR += sum;
   }

   /* choose the common vector (yuck!) */
   {
      GLint j1, j2;
      GLint v1 = 0, v2 = 0;
      GLfloat err = 1e9; /* big enough */
      GLfloat tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
      for (i = 0; i < n_comp; i++) {
         tv[0][i] = input[minColL][i];
         tv[1][i] = input[maxColL][i];
         tv[2][i] = input[minColR][i];
         tv[3][i] = input[maxColR][i];
      }
      for (j1 = 0; j1 < 2; j1++) {
         for (j2 = 2; j2 < 4; j2++) {
            GLfloat e = 0.0F;
            for (i = 0; i < n_comp; i++) {
               e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]);
            }
            if (e < err) {
               err = e;
               v1 = j1;
               v2 = j2;
            }
         }
      }
      for (i = 0; i < n_comp; i++) {
         vec[0][i] = tv[1 - v1][i];
         vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR);
         vec[2][i] = tv[5 - v2][i];
      }
   }

   /* left microtile */
   cc[0] = 0;
   if (minColL != maxColL) {
      /* compute interpolation vector */
      MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);

      /* add in texels */
      lolo = 0;
      for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
         GLint texel;
         /* interpolate color */
         CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
         /* add in texel */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -