Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include <tier0/platform.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <stdlib.h>
  11. #include "bitmap/float_bm.h"
  12. static float ScaleValue(float f, float overbright)
  13. {
  14. // map a value between 0..255 to the scale factor
  15. int ival=f;
  16. return ival*(overbright/255.0);
  17. }
  18. static float IScaleValue(float f, float overbright)
  19. {
  20. f*=(1.0/overbright);
  21. int ival=min(255,(int)ceil(f*255.0));
  22. return ival;
  23. }
  24. void MaybeSetScaleVaue(FloatBitMap_t const &orig, FloatBitMap_t &newbm, int x, int y,
  25. float newscale, float overbright)
  26. {
  27. // clamp the given scale value to the legal range for that pixel and regnerate the rgb
  28. // components.
  29. float maxc=max(max(orig.Pixel(x,y,0),orig.Pixel(x,y,1)),orig.Pixel(x,y,2));
  30. if (maxc==0.0)
  31. {
  32. // pixel is black. any scale value is fine.
  33. newbm.Pixel(x,y,3)=newscale;
  34. for(int c=0;c<3;c++)
  35. newbm.Pixel(x,y,c)=0;
  36. }
  37. else
  38. {
  39. // float desired_floatscale=maxc;
  40. float scale_we_will_get=ScaleValue(newscale,overbright);
  41. // if (scale_we_will_get >= desired_floatscale )
  42. {
  43. newbm.Pixel(x,y,3)=newscale;
  44. for(int c=0;c<3;c++)
  45. newbm.Pixel(x,y,c)=orig.Pixel(x,y,c)/(scale_we_will_get);
  46. }
  47. }
  48. }
  49. void FloatBitMap_t::Uncompress(float overbright)
  50. {
  51. for(int y=0;y<Height;y++)
  52. for(int x=0;x<Width;x++)
  53. {
  54. int iactual_alpha_value=255.0*Pixel(x,y,3);
  55. float actual_alpha_value=iactual_alpha_value*(1.0/255.0);
  56. for(int c=0;c<3;c++)
  57. {
  58. int iactual_color_value=255.0*Pixel(x,y,c);
  59. float actual_color_value=iactual_color_value*(1.0/255.0);
  60. Pixel(x,y,c)=actual_alpha_value*actual_color_value*overbright;
  61. }
  62. }
  63. }
  64. #define GAUSSIAN_WIDTH 5
  65. #define SQ(x) ((x)*(x))
  66. void FloatBitMap_t::CompressTo8Bits(float overbright)
  67. {
  68. FloatBitMap_t TmpFBM(Width,Height);
  69. // first, saturate to max overbright
  70. for(int y=0;y<Height;y++)
  71. for(int x=0;x<Width;x++)
  72. for(int c=0;c<3;c++)
  73. Pixel(x,y,c)=min(overbright,Pixel(x,y,c));
  74. // first pass - choose nominal scale values to convert to rgb,scale
  75. for(int y=0;y<Height;y++)
  76. for(int x=0;x<Width;x++)
  77. {
  78. // determine maximum component
  79. float maxc=max(max(Pixel(x,y,0),Pixel(x,y,1)),Pixel(x,y,2));
  80. if (maxc==0)
  81. {
  82. for(int c=0;c<4;c++)
  83. TmpFBM.Pixel(x,y,c)=0;
  84. }
  85. else
  86. {
  87. float desired_floatscale=maxc;
  88. float closest_iscale=IScaleValue(desired_floatscale, overbright);
  89. float scale_value_we_got=ScaleValue(closest_iscale, overbright );
  90. TmpFBM.Pixel(x,y,3)=closest_iscale;
  91. for(int c=0;c<3;c++)
  92. TmpFBM.Pixel(x,y,c)=Pixel(x,y,c)/scale_value_we_got;
  93. }
  94. }
  95. // now, refine scale values
  96. #ifdef FILTER_TO_REDUCE_LERP_ARTIFACTS
  97. // I haven't been able to come up with a filter which eleiminates objectionable artifacts on all
  98. // source textures. So, I've gone to doing the lerping in the shader.
  99. int pass=0;
  100. while(pass<1)
  101. {
  102. FloatBitMap_t temp_filtered(&TmpFBM);
  103. for(int y=0;y<Height;y++)
  104. {
  105. for(int x=0;x<Width;x++)
  106. {
  107. float sum_scales=0.0;
  108. float sum_weights=0.0;
  109. for(int yofs=-GAUSSIAN_WIDTH;yofs<=GAUSSIAN_WIDTH;yofs++)
  110. for(int xofs=-GAUSSIAN_WIDTH;xofs<=GAUSSIAN_WIDTH;xofs++)
  111. {
  112. float r=0.456*GAUSSIAN_WIDTH;
  113. r=0.26*GAUSSIAN_WIDTH;
  114. float x1=xofs/r;
  115. float y1=yofs/r;
  116. float a=(SQ(x1)+SQ(y1))/(2.0*SQ(r));
  117. float w=exp(-a);
  118. sum_scales+=w*TmpFBM.PixelClamped(x+xofs,y+yofs,3);
  119. sum_weights+=w;
  120. }
  121. int new_trial_scale=sum_scales*(1.0/sum_weights);
  122. MaybeSetScaleVaue(*this,temp_filtered,x,y,new_trial_scale,overbright);
  123. }
  124. }
  125. pass++;
  126. memcpy(TmpFBM.RGBAData,temp_filtered.RGBAData,Width*Height*4*sizeof(float));
  127. }
  128. #endif
  129. memcpy(RGBAData,TmpFBM.RGBAData,Width*Height*4*sizeof(float));
  130. // now, map scale to real value
  131. for(int y=0;y<Height;y++)
  132. for(int x=0;x<Width;x++)
  133. Pixel(x,y,3)*=(1.0/255.0);
  134. }