llcubemap.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:12k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llcubemap.cpp
  3.  * @brief LLCubeMap class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llworkerthread.h"
  34. #include "llcubemap.h"
  35. #include "v4coloru.h"
  36. #include "v3math.h"
  37. #include "v3dmath.h"
  38. #include "m3math.h"
  39. #include "m4math.h"
  40. #include "llrender.h"
  41. #include "llglheaders.h"
  42. const F32 epsilon = 1e-7f;
  43. const U16 RESOLUTION = 64;
  44. #if LL_DARWIN
  45. // mipmap generation on cubemap textures seems to be broken on the Mac for at least some cards.
  46. // Since the cubemap is small (64x64 per face) and doesn't have any fine detail, turning off mipmaps is a usable workaround.
  47. const BOOL use_cube_mipmaps = FALSE;
  48. #else
  49. const BOOL use_cube_mipmaps = FALSE;  //current build works best without cube mipmaps
  50. #endif
  51. bool LLCubeMap::sUseCubeMaps = true;
  52. LLCubeMap::LLCubeMap()
  53. : mTextureStage(0),
  54.   mTextureCoordStage(0),
  55.   mMatrixStage(0)
  56. {
  57. mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
  58. mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
  59. mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
  60. mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
  61. mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
  62. mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
  63. }
  64. LLCubeMap::~LLCubeMap()
  65. {
  66. }
  67. void LLCubeMap::initGL()
  68. {
  69. llassert(gGLManager.mInited);
  70. if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
  71. {
  72. // Not initialized, do stuff.
  73. if (mImages[0].isNull())
  74. {
  75. U32 texname = 0;
  76. LLImageGL::generateTextures(1, &texname);
  77. for (int i = 0; i < 6; i++)
  78. {
  79. mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
  80. mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
  81. mRawImages[i] = new LLImageRaw(64, 64, 4);
  82. mImages[i]->createGLTexture(0, mRawImages[i], texname);
  83. gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); 
  84. mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
  85. stop_glerror();
  86. }
  87. gGL.getTexUnit(0)->disable();
  88. }
  89. disable();
  90. }
  91. else
  92. {
  93. llwarns << "Using cube map without extension!" << llendl;
  94. }
  95. }
  96. void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages)
  97. {
  98. bool flip_x[6] = { false, true,  false, false, true,  false };
  99. bool flip_y[6] =  { true,  true,  true,  false, true,  true  };
  100. bool transpose[6] = { false, false, false, false, true,  true  };
  101. // Yes, I know that this is inefficient! - djs 08/08/02
  102. for (int i = 0; i < 6; i++)
  103. {
  104. const U8 *sd = rawimages[i]->getData();
  105. U8 *td = mRawImages[i]->getData();
  106. S32 offset = 0;
  107. S32 sx, sy, so;
  108. for (int y = 0; y < 64; y++)
  109. {
  110. for (int x = 0; x < 64; x++)
  111. {
  112. sx = x;
  113. sy = y;
  114. if (flip_y[i])
  115. {
  116. sy = 63 - y;
  117. }
  118. if (flip_x[i])
  119. {
  120. sx = 63 - x;
  121. }
  122. if (transpose[i])
  123. {
  124. S32 temp = sx;
  125. sx = sy;
  126. sy = temp;
  127. }
  128. so = 64*sy + sx;
  129. so *= 4;
  130. *(td + offset++) = *(sd + so++);
  131. *(td + offset++) = *(sd + so++);
  132. *(td + offset++) = *(sd + so++);
  133. *(td + offset++) = *(sd + so++);
  134. }
  135. }
  136. }
  137. }
  138. void LLCubeMap::initGLData()
  139. {
  140. for (int i = 0; i < 6; i++)
  141. {
  142. mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64);
  143. }
  144. }
  145. void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
  146. {
  147. if (!gGLManager.mIsDisabled)
  148. {
  149. initGL();
  150. initRawData(rawimages);
  151. initGLData();
  152. }
  153. }
  154. GLuint LLCubeMap::getGLName()
  155. {
  156. return mImages[0]->getTexName();
  157. }
  158. void LLCubeMap::bind()
  159. {
  160. gGL.getTexUnit(mTextureStage)->bind(this);
  161. }
  162. void LLCubeMap::enable(S32 stage)
  163. {
  164. enableTexture(stage);
  165. enableTextureCoords(stage);
  166. }
  167. void LLCubeMap::enableTexture(S32 stage)
  168. {
  169. mTextureStage = stage;
  170. if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
  171. {
  172. gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
  173. }
  174. }
  175. void LLCubeMap::enableTextureCoords(S32 stage)
  176. {
  177. mTextureCoordStage = stage;
  178. if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
  179. {
  180. if (stage > 0)
  181. {
  182. gGL.getTexUnit(stage)->activate();
  183. }
  184. glEnable(GL_TEXTURE_GEN_R);
  185. glEnable(GL_TEXTURE_GEN_S);
  186. glEnable(GL_TEXTURE_GEN_T);
  187. glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  188. glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  189. glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
  190. if (stage > 0)
  191. {
  192. gGL.getTexUnit(0)->activate();
  193. }
  194. }
  195. }
  196. void LLCubeMap::disable(void)
  197. {
  198. disableTexture();
  199. disableTextureCoords();
  200. }
  201. void LLCubeMap::disableTexture(void)
  202. {
  203. if (gGLManager.mHasCubeMap && mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
  204. {
  205. gGL.getTexUnit(mTextureStage)->disable();
  206. if (mTextureStage == 0)
  207. {
  208. gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
  209. }
  210. }
  211. }
  212. void LLCubeMap::disableTextureCoords(void)
  213. {
  214. if (gGLManager.mHasCubeMap && mTextureCoordStage >= 0 && LLCubeMap::sUseCubeMaps)
  215. {
  216. if (mTextureCoordStage > 0)
  217. {
  218. gGL.getTexUnit(mTextureCoordStage)->activate();
  219. }
  220. glDisable(GL_TEXTURE_GEN_S);
  221. glDisable(GL_TEXTURE_GEN_T);
  222. glDisable(GL_TEXTURE_GEN_R);
  223. if (mTextureCoordStage > 0)
  224. {
  225. gGL.getTexUnit(0)->activate();
  226. }
  227. }
  228. }
  229. void LLCubeMap::setMatrix(S32 stage)
  230. {
  231. mMatrixStage = stage;
  232. if (mMatrixStage < 0) return;
  233. if (stage > 0)
  234. {
  235. gGL.getTexUnit(stage)->activate();
  236. }
  237. LLVector3 x(LLVector3d(gGLModelView+0));
  238. LLVector3 y(LLVector3d(gGLModelView+4));
  239. LLVector3 z(LLVector3d(gGLModelView+8));
  240. LLMatrix3 mat3;
  241. mat3.setRows(x,y,z);
  242. LLMatrix4 trans(mat3);
  243. trans.transpose();
  244. glMatrixMode(GL_TEXTURE);
  245. glPushMatrix();
  246. glLoadMatrixf((F32 *)trans.mMatrix);
  247. glMatrixMode(GL_MODELVIEW);
  248. if (stage > 0)
  249. {
  250. gGL.getTexUnit(0)->activate();
  251. }
  252. }
  253. void LLCubeMap::restoreMatrix()
  254. {
  255. if (mMatrixStage < 0) return;
  256. if (mMatrixStage > 0)
  257. {
  258. gGL.getTexUnit(mMatrixStage)->activate();
  259. }
  260. glMatrixMode(GL_TEXTURE);
  261. glPopMatrix();
  262. glMatrixMode(GL_MODELVIEW);
  263. if (mMatrixStage > 0)
  264. {
  265. gGL.getTexUnit(0)->activate();
  266. }
  267. }
  268. void LLCubeMap::setReflection (void)
  269. {
  270. gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName());
  271. mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
  272. mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
  273. }
  274. LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
  275. {
  276. LLVector3 dir;
  277. const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
  278. const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
  279. const U8 i_coef = (curr_coef + 1) % 3;
  280. const U8 j_coef = (i_coef + 1) % 3;
  281. dir.mV[curr_coef] = side_dir;
  282. switch (side)
  283. {
  284. case 0: // negative X
  285. dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
  286. dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
  287. break;
  288. case 1: // positive X
  289. dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
  290. dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
  291. break;
  292. case 2: // negative Y
  293. dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
  294. dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
  295. break;
  296. case 3: // positive Y
  297. dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
  298. dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
  299. break;
  300. case 4: // negative Z
  301. dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
  302. dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
  303. break;
  304. case 5: // positive Z
  305. dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
  306. dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
  307. break;
  308. default:
  309. dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
  310. dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
  311. }
  312. dir.normVec();
  313. return dir;
  314. }
  315. BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
  316. U8 side, const LLVector3& dir) const
  317. {
  318. const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
  319. const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1
  320. const U8 i_coef = (curr_coef + 1) % 3;
  321. const U8 j_coef = (i_coef + 1) % 3;
  322. outside = TRUE;
  323. if (side_dir * dir.mV[curr_coef] < 0)
  324. return FALSE;
  325. LLVector3 ray;
  326. F32 norm_val = fabs(dir.mV[curr_coef]);
  327. if (norm_val < epsilon)
  328. norm_val = 1e-5f;
  329. ray.mV[curr_coef] = side_dir;
  330. ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
  331. ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
  332. const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
  333. const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
  334. switch (side)
  335. {
  336. case 0: // negative X
  337. v_val = RESOLUTION - i_val;
  338. h_val = j_val;
  339. break;
  340. case 1: // positive X
  341. v_val = RESOLUTION - i_val;
  342. h_val = RESOLUTION - j_val;
  343. break;
  344. case 2: // negative Y
  345. v_val = RESOLUTION - i_val;
  346. h_val = j_val;
  347. break;
  348. case 3: // positive Y
  349. v_val = i_val;
  350. h_val = j_val;
  351. break;
  352. case 4: // negative Z
  353. v_val = RESOLUTION - j_val;
  354. h_val = RESOLUTION - i_val;
  355. break;
  356. case 5: // positive Z
  357. v_val = RESOLUTION - j_val;
  358. h_val = i_val;
  359. break;
  360. default:
  361. v_val = i_val;
  362. h_val = j_val;
  363. }
  364. outside =  ((v_val < 0) || (v_val > RESOLUTION) ||
  365. (h_val < 0) || (h_val > RESOLUTION));
  366. return TRUE;
  367. }
  368. BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max, 
  369. U8 side, LLVector3 dir[4]) const
  370. {
  371. v_min = h_min = RESOLUTION;
  372. v_max = h_max = 0;
  373. BOOL fully_outside = TRUE;
  374. for (U8 vtx = 0; vtx < 4; ++vtx)
  375. {
  376. F32 v_val, h_val;
  377. BOOL outside;
  378. BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
  379. if (!outside)
  380. fully_outside = FALSE;
  381. if (consider)
  382. {
  383. if (v_val < v_min) v_min = v_val;
  384. if (v_val > v_max) v_max = v_val;
  385. if (h_val < h_min) h_min = h_val;
  386. if (h_val > h_max) h_max = h_val;
  387. }
  388. }
  389. v_min = llmax(0.0f, v_min);
  390. v_max = llmin(RESOLUTION - epsilon, v_max);
  391. h_min = llmax(0.0f, h_min);
  392. h_max = llmin(RESOLUTION - epsilon, h_max);
  393. return !fully_outside;
  394. }
  395. void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
  396. {
  397. F32 v_min, v_max, h_min, h_max;
  398. LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
  399. center.normVec();
  400. for (U8 side = 0; side < 6; ++side)
  401. {
  402. if (!project(v_min, v_max, h_min, h_max, side, dir))
  403. continue;
  404. U8 *td = mRawImages[side]->getData();
  405. U16 v_minu = (U16) v_min;
  406. U16 v_maxu = (U16) (ceil(v_max) + 0.5);
  407. U16 h_minu = (U16) h_min;
  408. U16 h_maxu = (U16) (ceil(h_max) + 0.5);
  409. for (U16 v = v_minu; v < v_maxu; ++v)
  410. for (U16 h = h_minu; h < h_maxu; ++h)
  411. //for (U16 v = 0; v < RESOLUTION; ++v)
  412. // for (U16 h = 0; h < RESOLUTION; ++h)
  413. {
  414. const LLVector3 ray = map(side, v, h);
  415. if (ray * center > 0.999)
  416. {
  417. const U32 offset = (RESOLUTION * v + h) * 4;
  418. for (U8 cc = 0; cc < 3; ++cc)
  419. td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
  420. }
  421. }
  422. mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64);
  423. }
  424. }
  425. void LLCubeMap::destroyGL()
  426. {
  427. for (S32 i = 0; i < 6; i++)
  428. {
  429. mImages[i] = NULL;
  430. }
  431. }